- Timestamp:
- Aug 3, 2009, 2:48:42 PM (15 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:
- a80fbdf, caf4ba
- Parents:
- 2319ed
- Location:
- src
- Files:
-
- 6 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Makefile.am
r2319ed r357fba 1 SOURCE = atom.cpp bond.cpp boundary.cpp builder.cpp config.cpp element.cpp ellipsoid.cpp helpers.cpp linkedcell.cpp moleculelist.cpp molecules.cpp parser.cpp periodentafel.cpp vector.cpp verbose.cpp2 HEADER = boundary.hpp defs.hpp ellipsoid.hpp helpers.hpp linkedcell.hpp molecules.hpp parser.hpp periodentafel.hpp stackclass.hpp vector.hpp1 SOURCE = atom.cpp bond.cpp boundary.cpp builder.cpp config.cpp element.cpp ellipsoid.cpp helpers.cpp linkedcell.cpp moleculelist.cpp molecules.cpp parser.cpp periodentafel.cpp tesselation.cpp tesselationhelpers.cpp vector.cpp verbose.cpp 2 HEADER = atom.hpp bond.hpp boundary.hpp defs.hpp ellipsoid.hpp helpers.hpp linkedcell.hpp molecules.hpp parser.hpp periodentafel.hpp stackclass.hpp tesselation.hpp tesselationhelpers.hpp vector.hpp 3 3 4 4 bin_PROGRAMS = molecuilder joiner analyzer -
src/atom.cpp
r2319ed r357fba 5 5 */ 6 6 7 #include " molecules.hpp"7 #include "atom.hpp" 8 8 9 9 /************************************* Functions for class atom *************************************/ … … 13 13 atom::atom() 14 14 { 15 Name = NULL;15 father = this; // generally, father is itself 16 16 previous = NULL; 17 17 next = NULL; 18 father = this; // generally, father is itself19 18 Ancestor = NULL; 20 19 type = NULL; 21 20 sort = NULL; 22 21 FixedIon = 0; 23 nr = -1;24 22 GraphNr = -1; 25 23 ComponentNr = NULL; … … 29 27 AdaptiveOrder = 0; 30 28 MaxOrder = false; 29 // set LCNode::Vector to our Vector 30 node = &x; 31 31 }; 32 32 33 33 /** Constructor of class atom. 34 *35 34 */ 36 35 atom::atom(atom *pointer) … … 41 40 father = this; // generally, father is itself 42 41 Ancestor = NULL; 42 GraphNr = -1; 43 ComponentNr = NULL; 44 IsCyclic = false; 45 SeparationVertex = false; 46 LowpointNr = -1; 47 AdaptiveOrder = 0; 48 MaxOrder = false; 43 49 type = pointer->type; // copy element of atom 44 50 x.CopyVector(&pointer->x); // copy coordination … … 54 60 atom::~atom() 55 61 { 56 Free((void **)&Name, "atom::~atom: *Name");57 62 Free((void **)&ComponentNr, "atom::~atom: *ComponentNr"); 58 63 }; -
src/bond.cpp
r2319ed r357fba 5 5 */ 6 6 7 #include " molecules.hpp"7 #include "bond.hpp" 8 8 9 9 -
src/boundary.cpp
r2319ed r357fba 1 1 #include "boundary.hpp" 2 #include "linkedcell.hpp" 3 #include "molecules.hpp" 4 #include <gsl/gsl_matrix.h> 5 #include <gsl/gsl_linalg.h> 6 #include <gsl/gsl_multimin.h> 7 #include <gsl/gsl_permutation.h> 8 9 #define DEBUG 1 10 #define DoSingleStepOutput 0 11 #define DoTecplotOutput 1 12 #define DoRaster3DOutput 1 13 #define DoVRMLOutput 1 14 #define TecplotSuffix ".dat" 15 #define Raster3DSuffix ".r3d" 16 #define VRMLSUffix ".wrl" 17 #define HULLEPSILON 1e-7 18 19 // ======================================== Points on Boundary ================================= 20 21 BoundaryPointSet::BoundaryPointSet() 22 { 23 LinesCount = 0; 24 Nr = -1; 25 } 26 ; 27 28 BoundaryPointSet::BoundaryPointSet(atom *Walker) 29 { 30 node = Walker; 31 LinesCount = 0; 32 Nr = Walker->nr; 33 } 34 ; 35 36 BoundaryPointSet::~BoundaryPointSet() 37 { 38 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 39 if (!lines.empty()) 40 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl; 41 node = NULL; 42 } 43 ; 44 45 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 46 { 47 cout << Verbose(6) << "Adding " << *this << " to line " << *line << "." 48 << endl; 49 if (line->endpoints[0] == this) 50 { 51 lines.insert(LinePair(line->endpoints[1]->Nr, line)); 52 } 53 else 54 { 55 lines.insert(LinePair(line->endpoints[0]->Nr, line)); 56 } 57 LinesCount++; 58 } 59 ; 60 61 ostream & 62 operator <<(ostream &ost, BoundaryPointSet &a) 63 { 64 ost << "[" << a.Nr << "|" << a.node->Name << "]"; 65 return ost; 66 } 67 ; 68 69 // ======================================== Lines on Boundary ================================= 70 71 BoundaryLineSet::BoundaryLineSet() 72 { 73 for (int i = 0; i < 2; i++) 74 endpoints[i] = NULL; 75 TrianglesCount = 0; 76 Nr = -1; 77 } 78 ; 79 80 BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number) 81 { 82 // set number 83 Nr = number; 84 // set endpoints in ascending order 85 SetEndpointsOrdered(endpoints, Point[0], Point[1]); 86 // add this line to the hash maps of both endpoints 87 Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding. 88 Point[1]->AddLine(this); // 89 // clear triangles list 90 TrianglesCount = 0; 91 cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl; 92 } 93 ; 94 95 BoundaryLineSet::~BoundaryLineSet() 96 { 97 int Numbers[2]; 98 Numbers[0] = endpoints[1]->Nr; 99 Numbers[1] = endpoints[0]->Nr; 100 for (int i = 0; i < 2; i++) { 101 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 102 // as there may be multiple lines with same endpoints, we have to go through each and find in the endpoint's line list this line set 103 pair<LineMap::iterator, LineMap::iterator> erasor = endpoints[i]->lines.equal_range(Numbers[i]); 104 for (LineMap::iterator Runner = erasor.first; Runner != erasor.second; Runner++) 105 if ((*Runner).second == this) { 106 endpoints[i]->lines.erase(Runner); 107 break; 108 } 109 if (endpoints[i]->lines.empty()) { 110 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 111 if (endpoints[i] != NULL) { 112 delete(endpoints[i]); 113 endpoints[i] = NULL; 114 } else 115 cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl; 116 } else 117 cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl; 118 } 119 if (!triangles.empty()) 120 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some triangles." << endl; 121 } 122 ; 123 124 void 125 BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 126 { 127 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." 128 << endl; 129 triangles.insert(TrianglePair(triangle->Nr, triangle)); 130 TrianglesCount++; 131 } 132 ; 133 134 /** Checks whether we have a common endpoint with given \a *line. 135 * \param *line other line to test 136 * \return true - common endpoint present, false - not connected 137 */ 138 bool BoundaryLineSet::IsConnectedTo(class BoundaryLineSet *line) 139 { 140 if ((endpoints[0] == line->endpoints[0]) || (endpoints[1] == line->endpoints[0]) || (endpoints[0] == line->endpoints[1]) || (endpoints[1] == line->endpoints[1])) 141 return true; 142 else 143 return false; 144 }; 145 146 /** Checks whether the adjacent triangles of a baseline are convex or not. 147 * We sum the two angles of each normal vector with a ficticious normnal vector from this baselinbe pointing outwards. 148 * If greater/equal M_PI than we are convex. 149 * \param *out output stream for debugging 150 * \return true - triangles are convex, false - concave or less than two triangles connected 151 */ 152 bool BoundaryLineSet::CheckConvexityCriterion(ofstream *out) 153 { 154 Vector BaseLineNormal; 155 double angle = 0; 156 // get the two triangles 157 if (TrianglesCount != 2) { 158 *out << Verbose(1) << "ERROR: Baseline " << this << " is connect to less than two triangles, Tesselation incomplete!" << endl; 159 return false; 160 } 161 // have a normal vector on the base line pointing outwards 162 BaseLineNormal.Zero(); 163 for(TriangleMap::iterator runner = triangles.begin(); runner != triangles.end(); runner++) 164 BaseLineNormal.AddVector(&runner->second->NormalVector); 165 BaseLineNormal.Normalize(); 166 // and calculate the sum of the angles with this normal vector and each of the triangle ones' 167 for(TriangleMap::iterator runner = triangles.begin(); runner != triangles.end(); runner++) 168 angle += BaseLineNormal.Angle(&runner->second->NormalVector); 169 170 if ((angle - M_PI) > -MYEPSILON) 171 return true; 172 else 173 return false; 174 } 175 176 /** Checks whether point is any of the two endpoints this line contains. 177 * \param *point point to test 178 * \return true - point is of the line, false - is not 179 */ 180 bool BoundaryLineSet::ContainsBoundaryPoint(class BoundaryPointSet *point) 181 { 182 for(int i=0;i<2;i++) 183 if (point == endpoints[i]) 184 return true; 185 return false; 186 }; 187 188 ostream & 189 operator <<(ostream &ost, BoundaryLineSet &a) 190 { 191 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 192 << a.endpoints[1]->node->Name << "]"; 193 return ost; 194 } 195 ; 196 197 // ======================================== Triangles on Boundary ================================= 198 199 200 BoundaryTriangleSet::BoundaryTriangleSet() 201 { 202 for (int i = 0; i < 3; i++) 203 { 204 endpoints[i] = NULL; 205 lines[i] = NULL; 206 } 207 Nr = -1; 208 } 209 ; 210 211 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], int number) 212 { 213 // set number 214 Nr = number; 215 // set lines 216 cout << Verbose(5) << "New triangle " << Nr << ":" << endl; 217 for (int i = 0; i < 3; i++) 218 { 219 lines[i] = line[i]; 220 lines[i]->AddTriangle(this); 221 } 222 // get ascending order of endpoints 223 map<int, class BoundaryPointSet *> OrderMap; 224 for (int i = 0; i < 3; i++) 225 // for all three lines 226 for (int j = 0; j < 2; j++) 227 { // for both endpoints 228 OrderMap.insert(pair<int, class BoundaryPointSet *> ( 229 line[i]->endpoints[j]->Nr, line[i]->endpoints[j])); 230 // and we don't care whether insertion fails 231 } 232 // set endpoints 233 int Counter = 0; 234 cout << Verbose(6) << " with end points "; 235 for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner 236 != OrderMap.end(); runner++) 237 { 238 endpoints[Counter] = runner->second; 239 cout << " " << *endpoints[Counter]; 240 Counter++; 241 } 242 if (Counter < 3) 243 { 244 cerr << "ERROR! We have a triangle with only two distinct endpoints!" 245 << endl; 246 //exit(1); 247 } 248 cout << "." << endl; 249 } 250 ; 251 252 BoundaryTriangleSet::~BoundaryTriangleSet() 253 { 254 for (int i = 0; i < 3; i++) { 255 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl; 256 lines[i]->triangles.erase(Nr); 257 if (lines[i]->triangles.empty()) { 258 if (lines[i] != NULL) { 259 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 260 delete (lines[i]); 261 lines[i] = NULL; 262 } else 263 cerr << "ERROR: This line " << i << " has already been free'd." << endl; 264 } else 265 cout << Verbose(5) << *lines[i] << " is still attached to another triangle." << endl; 266 } 267 } 268 ; 269 270 /** Calculates the normal vector for this triangle. 271 * Is made unique by comparison with \a OtherVector to point in the other direction. 272 * \param &OtherVector direction vector to make normal vector unique. 273 */ 274 void BoundaryTriangleSet::GetNormalVector(Vector &OtherVector) 275 { 276 // get normal vector 277 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, 278 &endpoints[2]->node->x); 279 280 // make it always point inward (any offset vector onto plane projected onto normal vector suffices) 281 if (NormalVector.Projection(&OtherVector) > 0) 282 NormalVector.Scale(-1.); 283 }; 284 285 /** Finds the point on the triangle \a *BTS the line defined by \a *MolCenter and \a *x crosses through. 286 * We call Vector::GetIntersectionWithPlane() to receive the intersection point with the plane 287 * This we test if it's really on the plane and whether it's inside the triangle on the plane or not. 288 * The latter is done as follows: if it's really outside, then for any endpoint of the triangle and it's opposite 289 * base line, the intersection between the line from endpoint to intersection and the base line will have a Vector::NormSquared() 290 * smaller than the first line. 291 * \param *out output stream for debugging 292 * \param *MolCenter offset vector of line 293 * \param *x second endpoint of line, minus \a *MolCenter is directional vector of line 294 * \param *Intersection intersection on plane on return 295 * \return true - \a *Intersection contains intersection on plane defined by triangle, false - zero vector if outside of triangle. 296 */ 297 bool BoundaryTriangleSet::GetIntersectionInsideTriangle(ofstream *out, Vector *MolCenter, Vector *x, Vector *Intersection) 298 { 299 Vector CrossPoint; 300 Vector helper; 301 int i=0; 302 303 if (Intersection->GetIntersectionWithPlane(out, &NormalVector, &endpoints[0]->node->x, MolCenter, x)) { 304 *out << Verbose(1) << "Alas! [Bronstein] failed - at least numerically - the intersection is not on the plane!" << endl; 305 return false; 306 } 307 308 // Calculate cross point between one baseline and the line from the third endpoint to intersection 309 do { 310 CrossPoint.GetIntersectionOfTwoLinesOnPlane(out, &endpoints[i%3]->node->x, &endpoints[(i+1)%3]->node->x, &endpoints[(i+2)%3]->node->x, Intersection); 311 helper.CopyVector(&endpoints[(i+1)%3]->node->x); 312 helper.SubtractVector(&endpoints[i%3]->node->x); 313 i++; 314 if (i>3) 315 break; 316 } while (CrossPoint.NormSquared() < MYEPSILON); 317 if (i>3) { 318 *out << Verbose(1) << "ERROR: Could not find any cross points, something's utterly wrong here!" << endl; 319 exit(255); 320 } 321 CrossPoint.SubtractVector(&endpoints[i%3]->node->x); 322 323 // check whether intersection is inside or not by comparing length of intersection and length of cross point 324 if ((CrossPoint.NormSquared() - helper.NormSquared()) > -MYEPSILON) { // inside 325 return true; 326 } else { // outside! 327 Intersection->Zero(); 328 return false; 329 } 330 }; 331 332 /** Checks whether lines is any of the three boundary lines this triangle contains. 333 * \param *line line to test 334 * \return true - line is of the triangle, false - is not 335 */ 336 bool BoundaryTriangleSet::ContainsBoundaryLine(class BoundaryLineSet *line) 337 { 338 for(int i=0;i<3;i++) 339 if (line == lines[i]) 340 return true; 341 return false; 342 }; 343 344 /** Checks whether point is any of the three endpoints this triangle contains. 345 * \param *point point to test 346 * \return true - point is of the triangle, false - is not 347 */ 348 bool BoundaryTriangleSet::ContainsBoundaryPoint(class BoundaryPointSet *point) 349 { 350 for(int i=0;i<3;i++) 351 if (point == endpoints[i]) 352 return true; 353 return false; 354 }; 355 356 ostream & 357 operator <<(ostream &ost, BoundaryTriangleSet &a) 358 { 359 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 360 << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 361 return ost; 362 } 363 ; 364 365 366 // ============================ CandidateForTesselation ============================= 367 368 CandidateForTesselation::CandidateForTesselation( 369 atom *candidate, BoundaryLineSet* line, Vector OptCandidateCenter, Vector OtherOptCandidateCenter 370 ) { 371 point = candidate; 372 BaseLine = line; 373 OptCenter.CopyVector(&OptCandidateCenter); 374 OtherOptCenter.CopyVector(&OtherOptCandidateCenter); 375 } 376 377 CandidateForTesselation::~CandidateForTesselation() { 378 point = NULL; 379 BaseLine = NULL; 380 } 2 3 #include<gsl/gsl_poly.h> 381 4 382 5 // ========================================== F U N C T I O N S ================================= 383 6 384 /** Finds the endpoint two lines are sharing.385 * \param *line1 first line386 * \param *line2 second line387 * \return point which is shared or NULL if none388 */389 class BoundaryPointSet *390 GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)391 {392 class BoundaryLineSet * lines[2] =393 { line1, line2 };394 class BoundaryPointSet *node = NULL;395 map<int, class BoundaryPointSet *> OrderMap;396 pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest;397 for (int i = 0; i < 2; i++)398 // for both lines399 for (int j = 0; j < 2; j++)400 { // for both endpoints401 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (402 lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));403 if (!OrderTest.second)404 { // if insertion fails, we have common endpoint405 node = OrderTest.first->second;406 cout << Verbose(5) << "Common endpoint of lines " << *line1407 << " and " << *line2 << " is: " << *node << "." << endl;408 j = 2;409 i = 2;410 break;411 }412 }413 return node;414 }415 ;416 417 /** Determines the boundary points of a cluster.418 * Does a projection per axis onto the orthogonal plane, transforms into spherical coordinates, sorts them by the angle419 * and looks at triples: if the middle has less a distance than the allowed maximum height of the triangle formed by the plane's420 * center and first and last point in the triple, it is thrown out.421 * \param *out output stream for debugging422 * \param *mol molecule structure representing the cluster423 */424 Boundaries *425 GetBoundaryPoints(ofstream *out, molecule *mol)426 {427 atom *Walker = NULL;428 PointMap PointsOnBoundary;429 LineMap LinesOnBoundary;430 TriangleMap TrianglesOnBoundary;431 Vector *MolCenter = mol->DetermineCenterOfAll(out);432 Vector helper;433 434 *out << Verbose(1) << "Finding all boundary points." << endl;435 Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)436 BoundariesTestPair BoundaryTestPair;437 Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;438 double radius, angle;439 // 3a. Go through every axis440 for (int axis = 0; axis < NDIM; axis++) {441 AxisVector.Zero();442 AngleReferenceVector.Zero();443 AngleReferenceNormalVector.Zero();444 AxisVector.x[axis] = 1.;445 AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;446 AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;447 448 *out << Verbose(1) << "Axisvector is " << AxisVector << " and AngleReferenceVector is " << AngleReferenceVector << ", and AngleReferenceNormalVector is " << AngleReferenceNormalVector << "." << endl;449 450 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours451 Walker = mol->start;452 while (Walker->next != mol->end) {453 Walker = Walker->next;454 Vector ProjectedVector;455 ProjectedVector.CopyVector(&Walker->x);456 ProjectedVector.SubtractVector(MolCenter);457 ProjectedVector.ProjectOntoPlane(&AxisVector);458 459 // correct for negative side460 radius = ProjectedVector.NormSquared();461 if (fabs(radius) > MYEPSILON)462 angle = ProjectedVector.Angle(&AngleReferenceVector);463 else464 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues465 466 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;467 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) {468 angle = 2. * M_PI - angle;469 }470 *out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): " << ProjectedVector << endl;471 BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle, DistancePair (radius, Walker)));472 if (!BoundaryTestPair.second) { // same point exists, check first r, then distance of original vectors to center of gravity473 *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl;474 *out << Verbose(2) << "Present vector: " << *BoundaryTestPair.first->second.second << endl;475 *out << Verbose(2) << "New vector: " << *Walker << endl;476 double tmp = ProjectedVector.NormSquared();477 if ((tmp - BoundaryTestPair.first->second.first) > MYEPSILON) {478 BoundaryTestPair.first->second.first = tmp;479 BoundaryTestPair.first->second.second = Walker;480 *out << Verbose(2) << "Keeping new vector due to larger projected distance " << tmp << "." << endl;481 } else if (fabs(tmp - BoundaryTestPair.first->second.first) < MYEPSILON) {482 helper.CopyVector(&Walker->x);483 helper.SubtractVector(MolCenter);484 tmp = helper.NormSquared();485 helper.CopyVector(&BoundaryTestPair.first->second.second->x);486 helper.SubtractVector(MolCenter);487 if (helper.NormSquared() < tmp) {488 BoundaryTestPair.first->second.second = Walker;489 *out << Verbose(2) << "Keeping new vector due to larger distance to molecule center " << helper.NormSquared() << "." << endl;490 } else {491 *out << Verbose(2) << "Keeping present vector due to larger distance to molecule center " << tmp << "." << endl;492 }493 } else {494 *out << Verbose(2) << "Keeping present vector due to larger projected distance " << tmp << "." << endl;495 }496 }497 }498 // printing all inserted for debugging499 // {500 // *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;501 // int i=0;502 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {503 // if (runner != BoundaryPoints[axis].begin())504 // *out << ", " << i << ": " << *runner->second.second;505 // else506 // *out << i << ": " << *runner->second.second;507 // i++;508 // }509 // *out << endl;510 // }511 // 3c. throw out points whose distance is less than the mean of left and right neighbours512 bool flag = false;513 *out << Verbose(1) << "Looking for candidates to kick out by convex condition ... " << endl;514 do { // do as long as we still throw one out per round515 flag = false;516 Boundaries::iterator left = BoundaryPoints[axis].end();517 Boundaries::iterator right = BoundaryPoints[axis].end();518 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {519 // set neighbours correctly520 if (runner == BoundaryPoints[axis].begin()) {521 left = BoundaryPoints[axis].end();522 } else {523 left = runner;524 }525 left--;526 right = runner;527 right++;528 if (right == BoundaryPoints[axis].end()) {529 right = BoundaryPoints[axis].begin();530 }531 // check distance532 533 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)534 {535 Vector SideA, SideB, SideC, SideH;536 SideA.CopyVector(&left->second.second->x);537 SideA.SubtractVector(MolCenter);538 SideA.ProjectOntoPlane(&AxisVector);539 // *out << "SideA: ";540 // SideA.Output(out);541 // *out << endl;542 543 SideB.CopyVector(&right->second.second->x);544 SideB.SubtractVector(MolCenter);545 SideB.ProjectOntoPlane(&AxisVector);546 // *out << "SideB: ";547 // SideB.Output(out);548 // *out << endl;549 550 SideC.CopyVector(&left->second.second->x);551 SideC.SubtractVector(&right->second.second->x);552 SideC.ProjectOntoPlane(&AxisVector);553 // *out << "SideC: ";554 // SideC.Output(out);555 // *out << endl;556 557 SideH.CopyVector(&runner->second.second->x);558 SideH.SubtractVector(MolCenter);559 SideH.ProjectOntoPlane(&AxisVector);560 // *out << "SideH: ";561 // SideH.Output(out);562 // *out << endl;563 564 // calculate each length565 double a = SideA.Norm();566 //double b = SideB.Norm();567 //double c = SideC.Norm();568 double h = SideH.Norm();569 // calculate the angles570 double alpha = SideA.Angle(&SideH);571 double beta = SideA.Angle(&SideC);572 double gamma = SideB.Angle(&SideH);573 double delta = SideC.Angle(&SideH);574 double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);575 //*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;576 *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;577 if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) < MYEPSILON) && ((h - MinDistance)) < -MYEPSILON) {578 // throw out point579 *out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;580 BoundaryPoints[axis].erase(runner);581 flag = true;582 }583 }584 }585 } while (flag);586 }587 delete(MolCenter);588 return BoundaryPoints;589 }590 ;591 7 592 8 /** Determines greatest diameters of a cluster defined by its convex envelope. … … 605 21 bool BoundaryFreeFlag = false; 606 22 Boundaries *BoundaryPoints = BoundaryPtr; 607 if (BoundaryPoints == NULL) 608 { 609 BoundaryFreeFlag = true; 610 BoundaryPoints = GetBoundaryPoints(out, mol); 611 } 612 else 613 { 614 *out << Verbose(1) << "Using given boundary points set." << endl; 615 } 23 if (BoundaryPoints == NULL) { 24 BoundaryFreeFlag = true; 25 BoundaryPoints = GetBoundaryPoints(out, mol); 26 } else { 27 *out << Verbose(1) << "Using given boundary points set." << endl; 28 } 616 29 // determine biggest "diameter" of cluster for each axis 617 30 Boundaries::iterator Neighbour, OtherNeighbour; … … 735 148 for (i=0;i<3;i++) { // print each node 736 149 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates 737 *vrmlfile << TriangleRunner->second->endpoints[i]->node-> x.x[j]-center->x[j] << " ";150 *vrmlfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " "; 738 151 *vrmlfile << "\t"; 739 152 } … … 790 203 for (i=0;i<3;i++) { // print each node 791 204 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates 792 *rasterfile << TriangleRunner->second->endpoints[i]->node-> x.x[j]-center->x[j] << " ";205 *rasterfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " "; 793 206 *rasterfile << "\t"; 794 207 } … … 821 234 *out << Verbose(2) << "The following triangles were created:"; 822 235 int Counter = 1; 823 atom*Walker = NULL;236 TesselPoint *Walker = NULL; 824 237 for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) { 825 238 Walker = target->second->node; 826 239 LookupList[Walker->nr] = Counter++; 827 *tecplot << Walker-> x.x[0] << " " << Walker->x.x[1] << " " << Walker->x.x[2] << " " << endl;240 *tecplot << Walker->node->x[0] << " " << Walker->node->x[1] << " " << Walker->node->x[2] << " " << endl; 828 241 } 829 242 *tecplot << endl; … … 837 250 } 838 251 } 252 253 254 /** Determines the boundary points of a cluster. 255 * Does a projection per axis onto the orthogonal plane, transforms into spherical coordinates, sorts them by the angle 256 * and looks at triples: if the middle has less a distance than the allowed maximum height of the triangle formed by the plane's 257 * center and first and last point in the triple, it is thrown out. 258 * \param *out output stream for debugging 259 * \param *mol molecule structure representing the cluster 260 */ 261 Boundaries *GetBoundaryPoints(ofstream *out, molecule *mol) 262 { 263 atom *Walker = NULL; 264 PointMap PointsOnBoundary; 265 LineMap LinesOnBoundary; 266 TriangleMap TrianglesOnBoundary; 267 Vector *MolCenter = mol->DetermineCenterOfAll(out); 268 Vector helper; 269 270 *out << Verbose(1) << "Finding all boundary points." << endl; 271 Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr) 272 BoundariesTestPair BoundaryTestPair; 273 Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector; 274 double radius, angle; 275 // 3a. Go through every axis 276 for (int axis = 0; axis < NDIM; axis++) { 277 AxisVector.Zero(); 278 AngleReferenceVector.Zero(); 279 AngleReferenceNormalVector.Zero(); 280 AxisVector.x[axis] = 1.; 281 AngleReferenceVector.x[(axis + 1) % NDIM] = 1.; 282 AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.; 283 284 *out << Verbose(1) << "Axisvector is " << AxisVector << " and AngleReferenceVector is " << AngleReferenceVector << ", and AngleReferenceNormalVector is " << AngleReferenceNormalVector << "." << endl; 285 286 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours 287 Walker = mol->start; 288 while (Walker->next != mol->end) { 289 Walker = Walker->next; 290 Vector ProjectedVector; 291 ProjectedVector.CopyVector(&Walker->x); 292 ProjectedVector.SubtractVector(MolCenter); 293 ProjectedVector.ProjectOntoPlane(&AxisVector); 294 295 // correct for negative side 296 radius = ProjectedVector.NormSquared(); 297 if (fabs(radius) > MYEPSILON) 298 angle = ProjectedVector.Angle(&AngleReferenceVector); 299 else 300 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 301 302 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 303 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) { 304 angle = 2. * M_PI - angle; 305 } 306 *out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): " << ProjectedVector << endl; 307 BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle, DistancePair (radius, Walker))); 308 if (!BoundaryTestPair.second) { // same point exists, check first r, then distance of original vectors to center of gravity 309 *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl; 310 *out << Verbose(2) << "Present vector: " << *BoundaryTestPair.first->second.second << endl; 311 *out << Verbose(2) << "New vector: " << *Walker << endl; 312 double tmp = ProjectedVector.NormSquared(); 313 if ((tmp - BoundaryTestPair.first->second.first) > MYEPSILON) { 314 BoundaryTestPair.first->second.first = tmp; 315 BoundaryTestPair.first->second.second = Walker; 316 *out << Verbose(2) << "Keeping new vector due to larger projected distance " << tmp << "." << endl; 317 } else if (fabs(tmp - BoundaryTestPair.first->second.first) < MYEPSILON) { 318 helper.CopyVector(&Walker->x); 319 helper.SubtractVector(MolCenter); 320 tmp = helper.NormSquared(); 321 helper.CopyVector(&BoundaryTestPair.first->second.second->x); 322 helper.SubtractVector(MolCenter); 323 if (helper.NormSquared() < tmp) { 324 BoundaryTestPair.first->second.second = Walker; 325 *out << Verbose(2) << "Keeping new vector due to larger distance to molecule center " << helper.NormSquared() << "." << endl; 326 } else { 327 *out << Verbose(2) << "Keeping present vector due to larger distance to molecule center " << tmp << "." << endl; 328 } 329 } else { 330 *out << Verbose(2) << "Keeping present vector due to larger projected distance " << tmp << "." << endl; 331 } 332 } 333 } 334 // printing all inserted for debugging 335 // { 336 // *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl; 337 // int i=0; 338 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 339 // if (runner != BoundaryPoints[axis].begin()) 340 // *out << ", " << i << ": " << *runner->second.second; 341 // else 342 // *out << i << ": " << *runner->second.second; 343 // i++; 344 // } 345 // *out << endl; 346 // } 347 // 3c. throw out points whose distance is less than the mean of left and right neighbours 348 bool flag = false; 349 *out << Verbose(1) << "Looking for candidates to kick out by convex condition ... " << endl; 350 do { // do as long as we still throw one out per round 351 flag = false; 352 Boundaries::iterator left = BoundaryPoints[axis].end(); 353 Boundaries::iterator right = BoundaryPoints[axis].end(); 354 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 355 // set neighbours correctly 356 if (runner == BoundaryPoints[axis].begin()) { 357 left = BoundaryPoints[axis].end(); 358 } else { 359 left = runner; 360 } 361 left--; 362 right = runner; 363 right++; 364 if (right == BoundaryPoints[axis].end()) { 365 right = BoundaryPoints[axis].begin(); 366 } 367 // check distance 368 369 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 370 { 371 Vector SideA, SideB, SideC, SideH; 372 SideA.CopyVector(&left->second.second->x); 373 SideA.SubtractVector(MolCenter); 374 SideA.ProjectOntoPlane(&AxisVector); 375 // *out << "SideA: "; 376 // SideA.Output(out); 377 // *out << endl; 378 379 SideB.CopyVector(&right->second.second->x); 380 SideB.SubtractVector(MolCenter); 381 SideB.ProjectOntoPlane(&AxisVector); 382 // *out << "SideB: "; 383 // SideB.Output(out); 384 // *out << endl; 385 386 SideC.CopyVector(&left->second.second->x); 387 SideC.SubtractVector(&right->second.second->x); 388 SideC.ProjectOntoPlane(&AxisVector); 389 // *out << "SideC: "; 390 // SideC.Output(out); 391 // *out << endl; 392 393 SideH.CopyVector(&runner->second.second->x); 394 SideH.SubtractVector(MolCenter); 395 SideH.ProjectOntoPlane(&AxisVector); 396 // *out << "SideH: "; 397 // SideH.Output(out); 398 // *out << endl; 399 400 // calculate each length 401 double a = SideA.Norm(); 402 //double b = SideB.Norm(); 403 //double c = SideC.Norm(); 404 double h = SideH.Norm(); 405 // calculate the angles 406 double alpha = SideA.Angle(&SideH); 407 double beta = SideA.Angle(&SideC); 408 double gamma = SideB.Angle(&SideH); 409 double delta = SideC.Angle(&SideH); 410 double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.); 411 //*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; 412 *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; 413 if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) < MYEPSILON) && ((h - MinDistance)) < -MYEPSILON) { 414 // throw out point 415 *out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl; 416 BoundaryPoints[axis].erase(runner); 417 flag = true; 418 } 419 } 420 } 421 } while (flag); 422 } 423 delete(MolCenter); 424 return BoundaryPoints; 425 }; 839 426 840 427 /** Tesselates the convex boundary by finding all boundary points. … … 959 546 << "Calculating the volume of the pyramids formed out of triangles and center of gravity." 960 547 << endl; 961 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner 962 != TesselStruct->TrianglesOnBoundary.end(); runner++) 548 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) 963 549 { // go through every triangle, calculate volume of its pyramid with CoG as peak 964 x.CopyVector(&runner->second->endpoints[0]->node->x); 965 x.SubtractVector(&runner->second->endpoints[1]->node->x); 966 y.CopyVector(&runner->second->endpoints[0]->node->x); 967 y.SubtractVector(&runner->second->endpoints[2]->node->x); 968 a = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared( 969 &runner->second->endpoints[1]->node->x)); 970 b = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared( 971 &runner->second->endpoints[2]->node->x)); 972 c = sqrt(runner->second->endpoints[2]->node->x.DistanceSquared( 973 &runner->second->endpoints[1]->node->x)); 550 x.CopyVector(runner->second->endpoints[0]->node->node); 551 x.SubtractVector(runner->second->endpoints[1]->node->node); 552 y.CopyVector(runner->second->endpoints[0]->node->node); 553 y.SubtractVector(runner->second->endpoints[2]->node->node); 554 a = sqrt(runner->second->endpoints[0]->node->node->DistanceSquared(runner->second->endpoints[1]->node->node)); 555 b = sqrt(runner->second->endpoints[0]->node->node->DistanceSquared(runner->second->endpoints[2]->node->node)); 556 c = sqrt(runner->second->endpoints[2]->node->node->DistanceSquared(runner->second->endpoints[1]->node->node)); 974 557 G = sqrt(((a + b + c) * (a + b + c) - 2 * (a * a + b * b + c * c)) / 16.); // area of tesselated triangle 975 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, 976 &runner->second->endpoints[1]->node->x, 977 &runner->second->endpoints[2]->node->x); 978 x.Scale(runner->second->endpoints[1]->node->x.Projection(&x)); 558 x.MakeNormalVector(runner->second->endpoints[0]->node->node, runner->second->endpoints[1]->node->node, runner->second->endpoints[2]->node->node); 559 x.Scale(runner->second->endpoints[1]->node->node->Projection(&x)); 979 560 h = x.Norm(); // distance of CoG to triangle 980 561 PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) … … 1227 808 }; 1228 809 1229 1230 // =========================================================== class TESSELATION ===========================================1231 1232 /** Constructor of class Tesselation.1233 */1234 Tesselation::Tesselation()1235 {1236 PointsOnBoundaryCount = 0;1237 LinesOnBoundaryCount = 0;1238 TrianglesOnBoundaryCount = 0;1239 TriangleFilesWritten = 0;1240 }1241 ;1242 1243 /** Constructor of class Tesselation.1244 * We have to free all points, lines and triangles.1245 */1246 Tesselation::~Tesselation()1247 {1248 cout << Verbose(1) << "Free'ing TesselStruct ... " << endl;1249 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) {1250 if (runner->second != NULL) {1251 delete (runner->second);1252 runner->second = NULL;1253 } else1254 cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl;1255 }1256 }1257 ;1258 1259 /** Gueses first starting triangle of the convex envelope.1260 * We guess the starting triangle by taking the smallest distance between two points and looking for a fitting third.1261 * \param *out output stream for debugging1262 * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster1263 */1264 void1265 Tesselation::GuessStartingTriangle(ofstream *out)1266 {1267 // 4b. create a starting triangle1268 // 4b1. create all distances1269 DistanceMultiMap DistanceMMap;1270 double distance, tmp;1271 Vector PlaneVector, TrialVector;1272 PointMap::iterator A, B, C; // three nodes of the first triangle1273 A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily1274 1275 // with A chosen, take each pair B,C and sort1276 if (A != PointsOnBoundary.end())1277 {1278 B = A;1279 B++;1280 for (; B != PointsOnBoundary.end(); B++)1281 {1282 C = B;1283 C++;1284 for (; C != PointsOnBoundary.end(); C++)1285 {1286 tmp = A->second->node->x.DistanceSquared(&B->second->node->x);1287 distance = tmp * tmp;1288 tmp = A->second->node->x.DistanceSquared(&C->second->node->x);1289 distance += tmp * tmp;1290 tmp = B->second->node->x.DistanceSquared(&C->second->node->x);1291 distance += tmp * tmp;1292 DistanceMMap.insert(DistanceMultiMapPair(distance, pair<1293 PointMap::iterator, PointMap::iterator> (B, C)));1294 }1295 }1296 }1297 // // listing distances1298 // *out << Verbose(1) << "Listing DistanceMMap:";1299 // for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {1300 // *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";1301 // }1302 // *out << endl;1303 // 4b2. pick three baselines forming a triangle1304 // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate1305 DistanceMultiMap::iterator baseline = DistanceMMap.begin();1306 for (; baseline != DistanceMMap.end(); baseline++)1307 {1308 // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate1309 // 2. next, we have to check whether all points reside on only one side of the triangle1310 // 3. construct plane vector1311 PlaneVector.MakeNormalVector(&A->second->node->x,1312 &baseline->second.first->second->node->x,1313 &baseline->second.second->second->node->x);1314 *out << Verbose(2) << "Plane vector of candidate triangle is ";1315 PlaneVector.Output(out);1316 *out << endl;1317 // 4. loop over all points1318 double sign = 0.;1319 PointMap::iterator checker = PointsOnBoundary.begin();1320 for (; checker != PointsOnBoundary.end(); checker++)1321 {1322 // (neglecting A,B,C)1323 if ((checker == A) || (checker == baseline->second.first) || (checker1324 == baseline->second.second))1325 continue;1326 // 4a. project onto plane vector1327 TrialVector.CopyVector(&checker->second->node->x);1328 TrialVector.SubtractVector(&A->second->node->x);1329 distance = TrialVector.Projection(&PlaneVector);1330 if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok1331 continue;1332 *out << Verbose(3) << "Projection of " << checker->second->node->Name1333 << " yields distance of " << distance << "." << endl;1334 tmp = distance / fabs(distance);1335 // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)1336 if ((sign != 0) && (tmp != sign))1337 {1338 // 4c. If so, break 4. loop and continue with next candidate in 1. loop1339 *out << Verbose(2) << "Current candidates: "1340 << A->second->node->Name << ","1341 << baseline->second.first->second->node->Name << ","1342 << baseline->second.second->second->node->Name << " leaves "1343 << checker->second->node->Name << " outside the convex hull."1344 << endl;1345 break;1346 }1347 else1348 { // note the sign for later1349 *out << Verbose(2) << "Current candidates: "1350 << A->second->node->Name << ","1351 << baseline->second.first->second->node->Name << ","1352 << baseline->second.second->second->node->Name << " leave "1353 << checker->second->node->Name << " inside the convex hull."1354 << endl;1355 sign = tmp;1356 }1357 // 4d. Check whether the point is inside the triangle (check distance to each node1358 tmp = checker->second->node->x.DistanceSquared(&A->second->node->x);1359 int innerpoint = 0;1360 if ((tmp < A->second->node->x.DistanceSquared(1361 &baseline->second.first->second->node->x)) && (tmp1362 < A->second->node->x.DistanceSquared(1363 &baseline->second.second->second->node->x)))1364 innerpoint++;1365 tmp = checker->second->node->x.DistanceSquared(1366 &baseline->second.first->second->node->x);1367 if ((tmp < baseline->second.first->second->node->x.DistanceSquared(1368 &A->second->node->x)) && (tmp1369 < baseline->second.first->second->node->x.DistanceSquared(1370 &baseline->second.second->second->node->x)))1371 innerpoint++;1372 tmp = checker->second->node->x.DistanceSquared(1373 &baseline->second.second->second->node->x);1374 if ((tmp < baseline->second.second->second->node->x.DistanceSquared(1375 &baseline->second.first->second->node->x)) && (tmp1376 < baseline->second.second->second->node->x.DistanceSquared(1377 &A->second->node->x)))1378 innerpoint++;1379 // 4e. If so, break 4. loop and continue with next candidate in 1. loop1380 if (innerpoint == 3)1381 break;1382 }1383 // 5. come this far, all on same side? Then break 1. loop and construct triangle1384 if (checker == PointsOnBoundary.end())1385 {1386 *out << "Looks like we have a candidate!" << endl;1387 break;1388 }1389 }1390 if (baseline != DistanceMMap.end())1391 {1392 BPS[0] = baseline->second.first->second;1393 BPS[1] = baseline->second.second->second;1394 BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1395 BPS[0] = A->second;1396 BPS[1] = baseline->second.second->second;1397 BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1398 BPS[0] = baseline->second.first->second;1399 BPS[1] = A->second;1400 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1401 1402 // 4b3. insert created triangle1403 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);1404 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));1405 TrianglesOnBoundaryCount++;1406 for (int i = 0; i < NDIM; i++)1407 {1408 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));1409 LinesOnBoundaryCount++;1410 }1411 1412 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;1413 }1414 else1415 {1416 *out << Verbose(1) << "No starting triangle found." << endl;1417 exit(255);1418 }1419 }1420 ;1421 1422 /** Tesselates the convex envelope of a cluster from a single starting triangle.1423 * The starting triangle is made out of three baselines. Each line in the final tesselated cluster may belong to at most1424 * 2 triangles. Hence, we go through all current lines:1425 * -# if the lines contains to only one triangle1426 * -# We search all points in the boundary1427 * -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to1428 * baseline in triangle plane pointing out of the triangle and normal vector of new triangle)1429 * -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors)1430 * -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount)1431 * \param *out output stream for debugging1432 * \param *configuration for IsAngstroem1433 * \param *mol the cluster as a molecule structure1434 */1435 void Tesselation::TesselateOnBoundary(ofstream *out, molecule *mol)1436 {1437 bool flag;1438 PointMap::iterator winner;1439 class BoundaryPointSet *peak = NULL;1440 double SmallestAngle, TempAngle;1441 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, helper, PropagationVector, *MolCenter = NULL;1442 LineMap::iterator LineChecker[2];1443 1444 MolCenter = mol->DetermineCenterOfAll(out);1445 // create a first tesselation with the given BoundaryPoints1446 do {1447 flag = false;1448 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++)1449 if (baseline->second->TrianglesCount == 1) {1450 // 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)1451 SmallestAngle = M_PI;1452 1453 // get peak point with respect to this base line's only triangle1454 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far1455 *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl;1456 for (int i = 0; i < 3; i++)1457 if ((BTS->endpoints[i] != baseline->second->endpoints[0]) && (BTS->endpoints[i] != baseline->second->endpoints[1]))1458 peak = BTS->endpoints[i];1459 *out << Verbose(3) << " and has peak " << *peak << "." << endl;1460 1461 // prepare some auxiliary vectors1462 Vector BaseLineCenter, BaseLine;1463 BaseLineCenter.CopyVector(&baseline->second->endpoints[0]->node->x);1464 BaseLineCenter.AddVector(&baseline->second->endpoints[1]->node->x);1465 BaseLineCenter.Scale(1. / 2.); // points now to center of base line1466 BaseLine.CopyVector(&baseline->second->endpoints[0]->node->x);1467 BaseLine.SubtractVector(&baseline->second->endpoints[1]->node->x);1468 1469 // offset to center of triangle1470 CenterVector.Zero();1471 for (int i = 0; i < 3; i++)1472 CenterVector.AddVector(&BTS->endpoints[i]->node->x);1473 CenterVector.Scale(1. / 3.);1474 *out << Verbose(4) << "CenterVector of base triangle is " << CenterVector << endl;1475 1476 // normal vector of triangle1477 NormalVector.CopyVector(MolCenter);1478 NormalVector.SubtractVector(&CenterVector);1479 BTS->GetNormalVector(NormalVector);1480 NormalVector.CopyVector(&BTS->NormalVector);1481 *out << Verbose(4) << "NormalVector of base triangle is " << NormalVector << endl;1482 1483 // vector in propagation direction (out of triangle)1484 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)1485 PropagationVector.MakeNormalVector(&BaseLine, &NormalVector);1486 TempVector.CopyVector(&CenterVector);1487 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!1488 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;1489 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline1490 PropagationVector.Scale(-1.);1491 *out << Verbose(4) << "PropagationVector of base triangle is " << PropagationVector << endl;1492 winner = PointsOnBoundary.end();1493 1494 // loop over all points and calculate angle between normal vector of new and present triangle1495 for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) {1496 if ((target->second != baseline->second->endpoints[0]) && (target->second != baseline->second->endpoints[1])) { // don't take the same endpoints1497 *out << Verbose(3) << "Target point is " << *(target->second) << ":" << endl;1498 1499 // first check direction, so that triangles don't intersect1500 VirtualNormalVector.CopyVector(&target->second->node->x);1501 VirtualNormalVector.SubtractVector(&BaseLineCenter); // points from center of base line to target1502 VirtualNormalVector.ProjectOntoPlane(&NormalVector);1503 TempAngle = VirtualNormalVector.Angle(&PropagationVector);1504 *out << Verbose(4) << "VirtualNormalVector is " << VirtualNormalVector << " and PropagationVector is " << PropagationVector << "." << endl;1505 if (TempAngle > (M_PI/2.)) { // no bends bigger than Pi/2 (90 degrees)1506 *out << Verbose(4) << "Angle on triangle plane between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", bad direction!" << endl;1507 continue;1508 } else1509 *out << Verbose(4) << "Angle on triangle plane between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", good direction!" << endl;1510 1511 // check first and second endpoint (if any connecting line goes to target has at least not more than 1 triangle)1512 LineChecker[0] = baseline->second->endpoints[0]->lines.find(target->first);1513 LineChecker[1] = baseline->second->endpoints[1]->lines.find(target->first);1514 if (((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[0]->second->TrianglesCount == 2))) {1515 *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;1516 continue;1517 }1518 if (((LineChecker[1] != baseline->second->endpoints[1]->lines.end()) && (LineChecker[1]->second->TrianglesCount == 2))) {1519 *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;1520 continue;1521 }1522 1523 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)1524 if ((((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) && (GetCommonEndpoint(LineChecker[0]->second, LineChecker[1]->second) == peak)))) {1525 *out << Verbose(4) << "Current target is peak!" << endl;1526 continue;1527 }1528 1529 // check for linear dependence1530 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);1531 TempVector.SubtractVector(&target->second->node->x);1532 helper.CopyVector(&baseline->second->endpoints[1]->node->x);1533 helper.SubtractVector(&target->second->node->x);1534 helper.ProjectOntoPlane(&TempVector);1535 if (fabs(helper.NormSquared()) < MYEPSILON) {1536 *out << Verbose(4) << "Chosen set of vectors is linear dependent." << endl;1537 continue;1538 }1539 1540 // in case NOT both were found, create virtually this triangle, get its normal vector, calculate angle1541 flag = true;1542 VirtualNormalVector.MakeNormalVector(&baseline->second->endpoints[0]->node->x, &baseline->second->endpoints[1]->node->x, &target->second->node->x);1543 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);1544 TempVector.AddVector(&baseline->second->endpoints[1]->node->x);1545 TempVector.AddVector(&target->second->node->x);1546 TempVector.Scale(1./3.);1547 TempVector.SubtractVector(MolCenter);1548 // make it always point outward1549 if (VirtualNormalVector.Projection(&TempVector) < 0)1550 VirtualNormalVector.Scale(-1.);1551 // calculate angle1552 TempAngle = NormalVector.Angle(&VirtualNormalVector);1553 *out << Verbose(4) << "NormalVector is " << VirtualNormalVector << " and the angle is " << TempAngle << "." << endl;1554 if ((SmallestAngle - TempAngle) > MYEPSILON) { // set to new possible winner1555 SmallestAngle = TempAngle;1556 winner = target;1557 *out << Verbose(4) << "New winner " << *winner->second->node << " due to smaller angle between normal vectors." << endl;1558 } else if (fabs(SmallestAngle - TempAngle) < MYEPSILON) { // check the angle to propagation, both possible targets are in one plane! (their normals have same angle)1559 // hence, check the angles to some normal direction from our base line but in this common plane of both targets...1560 helper.CopyVector(&target->second->node->x);1561 helper.SubtractVector(&BaseLineCenter);1562 helper.ProjectOntoPlane(&BaseLine);1563 // ...the one with the smaller angle is the better candidate1564 TempVector.CopyVector(&target->second->node->x);1565 TempVector.SubtractVector(&BaseLineCenter);1566 TempVector.ProjectOntoPlane(&VirtualNormalVector);1567 TempAngle = TempVector.Angle(&helper);1568 TempVector.CopyVector(&winner->second->node->x);1569 TempVector.SubtractVector(&BaseLineCenter);1570 TempVector.ProjectOntoPlane(&VirtualNormalVector);1571 if (TempAngle < TempVector.Angle(&helper)) {1572 TempAngle = NormalVector.Angle(&VirtualNormalVector);1573 SmallestAngle = TempAngle;1574 winner = target;1575 *out << Verbose(4) << "New winner " << *winner->second->node << " due to smaller angle " << TempAngle << " to propagation direction." << endl;1576 } else1577 *out << Verbose(4) << "Keeping old winner " << *winner->second->node << " due to smaller angle to propagation direction." << endl;1578 } else1579 *out << Verbose(4) << "Keeping old winner " << *winner->second->node << " due to smaller angle between normal vectors." << endl;1580 }1581 } // end of loop over all boundary points1582 1583 // 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 triangle1584 if (winner != PointsOnBoundary.end()) {1585 *out << Verbose(2) << "Winning target point is " << *(winner->second) << " with angle " << SmallestAngle << "." << endl;1586 // create the lins of not yet present1587 BLS[0] = baseline->second;1588 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)1589 LineChecker[0] = baseline->second->endpoints[0]->lines.find(winner->first);1590 LineChecker[1] = baseline->second->endpoints[1]->lines.find(winner->first);1591 if (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) { // create1592 BPS[0] = baseline->second->endpoints[0];1593 BPS[1] = winner->second;1594 BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1595 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[1]));1596 LinesOnBoundaryCount++;1597 } else1598 BLS[1] = LineChecker[0]->second;1599 if (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) { // create1600 BPS[0] = baseline->second->endpoints[1];1601 BPS[1] = winner->second;1602 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1603 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[2]));1604 LinesOnBoundaryCount++;1605 } else1606 BLS[2] = LineChecker[1]->second;1607 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);1608 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));1609 TrianglesOnBoundaryCount++;1610 } else {1611 *out << Verbose(1) << "I could not determine a winner for this baseline " << *(baseline->second) << "." << endl;1612 }1613 1614 // 5d. If the set of lines is not yet empty, go to 5. and continue1615 } else1616 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl;1617 } while (flag);1618 1619 // exit1620 delete(MolCenter);1621 };1622 1623 /** Inserts all atoms outside of the tesselated surface into it by adding new triangles.1624 * \param *out output stream for debugging1625 * \param *mol molecule structure with atoms1626 * \return true - all straddling points insert, false - something went wrong1627 */1628 bool Tesselation::InsertStraddlingPoints(ofstream *out, molecule *mol)1629 {1630 Vector Intersection;1631 atom *Walker = mol->start;1632 Vector *MolCenter = mol->DetermineCenterOfAll(out);1633 while (Walker->next != mol->end) { // we only have to go once through all points, as boundary can become only bigger1634 // get the next triangle1635 BTS = FindClosestTriangleToPoint(out, &Walker->x);1636 if (BTS == NULL) {1637 *out << Verbose(1) << "ERROR: No triangle closest to " << Walker << " was found." << endl;1638 return false;1639 }1640 // get the intersection point1641 if (BTS->GetIntersectionInsideTriangle(out, MolCenter, &Walker->x, &Intersection)) {1642 // we have the intersection, check whether in- or outside of boundary1643 if ((MolCenter->DistanceSquared(&Walker->x) - MolCenter->DistanceSquared(&Intersection)) < -MYEPSILON) {1644 // inside, next!1645 *out << Verbose(4) << Walker << " is inside wrt triangle " << BTS << "." << endl;1646 } else {1647 // outside!1648 *out << Verbose(3) << Walker << " is outside wrt triangle " << BTS << "." << endl;1649 class BoundaryLineSet *OldLines[3], *NewLines[3];1650 class BoundaryPointSet *OldPoints[3], *NewPoint;1651 // store the three old lines and old points1652 for (int i=0;i<3;i++) {1653 OldLines[i] = BTS->lines[i];1654 OldPoints[i] = BTS->endpoints[i];1655 }1656 // add Walker to boundary points1657 AddPoint(Walker);1658 if (BPS[0] == NULL)1659 NewPoint = BPS[0];1660 else1661 continue;1662 // remove triangle1663 TrianglesOnBoundary.erase(BTS->Nr);1664 // create three new boundary lines1665 for (int i=0;i<3;i++) {1666 BPS[0] = NewPoint;1667 BPS[1] = OldPoints[i];1668 NewLines[i] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);1669 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, NewLines[i])); // no need for check for unique insertion as BPS[0] is definitely a new one1670 LinesOnBoundaryCount++;1671 }1672 // create three new triangle with new point1673 for (int i=0;i<3;i++) { // find all baselines1674 BLS[0] = OldLines[i];1675 int n = 1;1676 for (int j=0;j<3;j++) {1677 if (NewLines[j]->IsConnectedTo(BLS[0])) {1678 if (n>2) {1679 *out << Verbose(1) << "ERROR: " << BLS[0] << " connects to all of the new lines?!" << endl;1680 return false;1681 } else1682 BLS[n++] = NewLines[j];1683 }1684 }1685 // create the triangle1686 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);1687 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));1688 TrianglesOnBoundaryCount++;1689 }1690 }1691 } else { // something is wrong with FindClosestTriangleToPoint!1692 *out << Verbose(1) << "ERROR: The closest triangle did not produce an intersection!" << endl;1693 return false;1694 }1695 }1696 1697 // exit1698 delete(MolCenter);1699 return true;1700 };1701 1702 /** Goes over all baselines and checks whether adjacent triangles and convex to each other.1703 * \param *out output stream for debugging1704 * \return true - all baselines were corrected, false - there are still concave pieces1705 */1706 bool Tesselation::CorrectConcaveBaselines(ofstream *out)1707 {1708 class BoundaryTriangleSet *triangle[2];1709 class BoundaryLineSet *OldLines[4], *NewLine;1710 class BoundaryPointSet *OldPoints[2];1711 Vector BaseLineNormal;1712 class BoundaryLineSet *Base = NULL;1713 int OldTriangles[2], OldBaseLine;1714 int i;1715 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) {1716 Base = baseline->second;1717 1718 // check convexity1719 if (Base->CheckConvexityCriterion(out)) { // triangles are convex1720 *out << Verbose(3) << Base << " has two convex triangles." << endl;1721 } else { // not convex!1722 // get the two triangles1723 i=0;1724 for(TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++)1725 triangle[i++] = runner->second;1726 // gather four endpoints and four lines1727 for (int j=0;j<4;j++)1728 OldLines[j] = NULL;1729 for (int j=0;j<2;j++)1730 OldPoints[j] = NULL;1731 i=0;1732 for (int m=0;m<2;m++) { // go over both triangles1733 for (int j=0;j<3;j++) { // all of their endpoints and baselines1734 if (triangle[m]->lines[j] != Base) // pick not the central baseline1735 OldLines[i++] = triangle[m]->lines[j];1736 if (!Base->ContainsBoundaryPoint(triangle[m]->endpoints[j])) // and neither of its endpoints1737 OldPoints[m] = triangle[m]->endpoints[j];1738 }1739 }1740 if (i<4) {1741 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;1742 return false;1743 }1744 for (int j=0;j<4;j++)1745 if (OldLines[j] == NULL) {1746 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;1747 return false;1748 }1749 for (int j=0;j<2;j++)1750 if (OldPoints[j] == NULL) {1751 *out << Verbose(1) << "ERROR: We have not gathered enough endpoints!" << endl;1752 return false;1753 }1754 1755 // remove triangles1756 for (int j=0;j<2;j++) {1757 OldTriangles[j] = triangle[j]->Nr;1758 TrianglesOnBoundary.erase(OldTriangles[j]);1759 triangle[j] = NULL;1760 }1761 1762 // remove baseline1763 OldBaseLine = Base->Nr;1764 LinesOnBoundary.erase(OldBaseLine);1765 Base = NULL;1766 1767 // construct new baseline (with same number as old one)1768 BPS[0] = OldPoints[0];1769 BPS[1] = OldPoints[1];1770 NewLine = new class BoundaryLineSet(BPS, OldBaseLine);1771 LinesOnBoundary.insert(LinePair(OldBaseLine, NewLine)); // no need for check for unique insertion as NewLine is definitely a new one1772 1773 // construct new triangles with flipped baseline1774 i=-1;1775 if (BLS[0]->IsConnectedTo(OldLines[2]))1776 i=2;1777 if (BLS[0]->IsConnectedTo(OldLines[2]))1778 i=3;1779 if (i!=-1) {1780 BLS[0] = OldLines[0];1781 BLS[1] = OldLines[i];1782 BLS[2] = NewLine;1783 BTS = new class BoundaryTriangleSet(BLS, OldTriangles[0]);1784 TrianglesOnBoundary.insert(TrianglePair(OldTriangles[0], BTS));1785 1786 BLS[0] = (i==2 ? OldLines[3] : OldLines[2]);1787 BLS[1] = OldLines[1];1788 BLS[2] = NewLine;1789 BTS = new class BoundaryTriangleSet(BLS, OldTriangles[1]);1790 TrianglesOnBoundary.insert(TrianglePair(OldTriangles[1], BTS));1791 } else {1792 *out << Verbose(1) << "The four old lines do not connect, something's utterly wrong here!" << endl;1793 return false;1794 }1795 }1796 }1797 return true;1798 };1799 1800 1801 /** States whether point is in- or outside of a tesselated surface.1802 * \param *pointer point to be checked1803 * \return true - is inside, false - is outside1804 */1805 bool Tesselation::IsInside(Vector *pointer)1806 {1807 1808 // hier kommt dann Saskias Routine hin...1809 1810 return true;1811 };1812 1813 /** Finds the closest triangle to a given point.1814 * \param *out output stream for debugging1815 * \param *x second endpoint of line1816 * \return pointer triangle that is closest, NULL if none was found1817 */1818 class BoundaryTriangleSet * Tesselation::FindClosestTriangleToPoint(ofstream *out, Vector *x)1819 {1820 class BoundaryTriangleSet *triangle = NULL;1821 1822 // hier kommt dann Saskias Routine hin...1823 1824 return triangle;1825 };1826 1827 /** Adds an atom to the tesselation::PointsOnBoundary list.1828 * \param *Walker atom to add1829 */1830 void1831 Tesselation::AddPoint(atom *Walker)1832 {1833 PointTestPair InsertUnique;1834 BPS[0] = new class BoundaryPointSet(Walker);1835 InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));1836 if (InsertUnique.second) // if new point was not present before, increase counter1837 PointsOnBoundaryCount++;1838 else {1839 delete(BPS[0]);1840 BPS[0] = NULL;1841 }1842 }1843 ;1844 1845 /** Adds point to Tesselation::PointsOnBoundary if not yet present.1846 * Tesselation::TPS is set to either this new BoundaryPointSet or to the existing one of not unique.1847 * @param Candidate point to add1848 * @param n index for this point in Tesselation::TPS array1849 */1850 void1851 Tesselation::AddTrianglePoint(atom* Candidate, int n)1852 {1853 PointTestPair InsertUnique;1854 TPS[n] = new class BoundaryPointSet(Candidate);1855 InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));1856 if (InsertUnique.second) { // if new point was not present before, increase counter1857 PointsOnBoundaryCount++;1858 } else {1859 delete TPS[n];1860 cout << Verbose(3) << "Atom " << *((InsertUnique.first)->second->node) << " is already present in PointsOnBoundary." << endl;1861 TPS[n] = (InsertUnique.first)->second;1862 }1863 }1864 ;1865 1866 /** Function tries to add line from current Points in BPS to BoundaryLineSet.1867 * If successful it raises the line count and inserts the new line into the BLS,1868 * if unsuccessful, it writes the line which had been present into the BLS, deleting the new constructed one.1869 * @param *a first endpoint1870 * @param *b second endpoint1871 * @param n index of Tesselation::BLS giving the line with both endpoints1872 */1873 void Tesselation::AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n) {1874 bool insertNewLine = true;1875 1876 if (a->lines.find(b->node->nr) != a->lines.end()) {1877 LineMap::iterator FindLine;1878 pair<LineMap::iterator,LineMap::iterator> FindPair;1879 FindPair = a->lines.equal_range(b->node->nr);1880 1881 for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {1882 // If there is a line with less than two attached triangles, we don't need a new line.1883 if (FindLine->second->TrianglesCount < 2) {1884 insertNewLine = false;1885 cout << Verbose(3) << "Using existing line " << *FindLine->second << endl;1886 1887 BPS[0] = FindLine->second->endpoints[0];1888 BPS[1] = FindLine->second->endpoints[1];1889 BLS[n] = FindLine->second;1890 1891 break;1892 }1893 }1894 }1895 1896 if (insertNewLine) {1897 AlwaysAddTriangleLine(a, b, n);1898 }1899 }1900 ;1901 1902 /**1903 * Adds lines from each of the current points in the BPS to BoundaryLineSet.1904 * Raises the line count and inserts the new line into the BLS.1905 *1906 * @param *a first endpoint1907 * @param *b second endpoint1908 * @param n index of Tesselation::BLS giving the line with both endpoints1909 */1910 void Tesselation::AlwaysAddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n)1911 {1912 cout << Verbose(3) << "Adding line between " << *(a->node) << " and " << *(b->node) << "." << endl;1913 BPS[0] = a;1914 BPS[1] = b;1915 BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); // this also adds the line to the local maps1916 // add line to global map1917 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));1918 // increase counter1919 LinesOnBoundaryCount++;1920 };1921 1922 /** Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm).1923 * Furthermore it adds the triangle to all of its lines, in order to recognize those which are saturated later.1924 */1925 void1926 Tesselation::AddTriangle()1927 {1928 cout << Verbose(1) << "Adding triangle to global TrianglesOnBoundary map." << endl;1929 1930 // add triangle to global map1931 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));1932 TrianglesOnBoundaryCount++;1933 1934 // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet1935 }1936 ;1937 1938 1939 double det_get(gsl_matrix *A, int inPlace) {1940 /*1941 inPlace = 1 => A is replaced with the LU decomposed copy.1942 inPlace = 0 => A is retained, and a copy is used for LU.1943 */1944 1945 double det;1946 int signum;1947 gsl_permutation *p = gsl_permutation_alloc(A->size1);1948 gsl_matrix *tmpA;1949 1950 if (inPlace)1951 tmpA = A;1952 else {1953 gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);1954 gsl_matrix_memcpy(tmpA , A);1955 }1956 1957 1958 gsl_linalg_LU_decomp(tmpA , p , &signum);1959 det = gsl_linalg_LU_det(tmpA , signum);1960 gsl_permutation_free(p);1961 if (! inPlace)1962 gsl_matrix_free(tmpA);1963 1964 return det;1965 };1966 1967 void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS)1968 {1969 gsl_matrix *A = gsl_matrix_calloc(3,3);1970 double m11, m12, m13, m14;1971 1972 for(int i=0;i<3;i++) {1973 gsl_matrix_set(A, i, 0, a.x[i]);1974 gsl_matrix_set(A, i, 1, b.x[i]);1975 gsl_matrix_set(A, i, 2, c.x[i]);1976 }1977 m11 = det_get(A, 1);1978 1979 for(int i=0;i<3;i++) {1980 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);1981 gsl_matrix_set(A, i, 1, b.x[i]);1982 gsl_matrix_set(A, i, 2, c.x[i]);1983 }1984 m12 = det_get(A, 1);1985 1986 for(int i=0;i<3;i++) {1987 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);1988 gsl_matrix_set(A, i, 1, a.x[i]);1989 gsl_matrix_set(A, i, 2, c.x[i]);1990 }1991 m13 = det_get(A, 1);1992 1993 for(int i=0;i<3;i++) {1994 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);1995 gsl_matrix_set(A, i, 1, a.x[i]);1996 gsl_matrix_set(A, i, 2, b.x[i]);1997 }1998 m14 = det_get(A, 1);1999 2000 if (fabs(m11) < MYEPSILON)2001 cerr << "ERROR: three points are colinear." << endl;2002 2003 center->x[0] = 0.5 * m12/ m11;2004 center->x[1] = -0.5 * m13/ m11;2005 center->x[2] = 0.5 * m14/ m11;2006 2007 if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)2008 cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;2009 2010 gsl_matrix_free(A);2011 };2012 2013 2014 2015 /**2016 * Function returns center of sphere with RADIUS, which rests on points a, b, c2017 * @param Center this vector will be used for return2018 * @param a vector first point of triangle2019 * @param b vector second point of triangle2020 * @param c vector third point of triangle2021 * @param *Umkreismittelpunkt new cneter point of circumference2022 * @param Direction vector indicates up/down2023 * @param AlternativeDirection vecotr, needed in case the triangles have 90 deg angle2024 * @param Halfplaneindicator double indicates whether Direction is up or down2025 * @param AlternativeIndicator doube indicates in case of orthogonal triangles which direction of AlternativeDirection is suitable2026 * @param alpha double angle at a2027 * @param beta double, angle at b2028 * @param gamma, double, angle at c2029 * @param Radius, double2030 * @param Umkreisradius double radius of circumscribing circle2031 */2032 void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection,2033 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)2034 {2035 Vector TempNormal, helper;2036 double Restradius;2037 Vector OtherCenter;2038 cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";2039 Center->Zero();2040 helper.CopyVector(&a);2041 helper.Scale(sin(2.*alpha));2042 Center->AddVector(&helper);2043 helper.CopyVector(&b);2044 helper.Scale(sin(2.*beta));2045 Center->AddVector(&helper);2046 helper.CopyVector(&c);2047 helper.Scale(sin(2.*gamma));2048 Center->AddVector(&helper);2049 //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;2050 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));2051 NewUmkreismittelpunkt->CopyVector(Center);2052 cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";2053 // Here we calculated center of circumscribing circle, using barycentric coordinates2054 cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";2055 2056 TempNormal.CopyVector(&a);2057 TempNormal.SubtractVector(&b);2058 helper.CopyVector(&a);2059 helper.SubtractVector(&c);2060 TempNormal.VectorProduct(&helper);2061 if (fabs(HalfplaneIndicator) < MYEPSILON)2062 {2063 if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))2064 {2065 TempNormal.Scale(-1);2066 }2067 }2068 else2069 {2070 if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)2071 {2072 TempNormal.Scale(-1);2073 }2074 }2075 2076 TempNormal.Normalize();2077 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);2078 cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";2079 TempNormal.Scale(Restradius);2080 cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";2081 2082 Center->AddVector(&TempNormal);2083 cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";2084 get_sphere(&OtherCenter, a, b, c, RADIUS);2085 cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";2086 cout << Verbose(3) << "End of Get_center_of_sphere.\n";2087 };2088 2089 2090 /** Constructs the center of the circumcircle defined by three points \a *a, \a *b and \a *c.2091 * \param *Center new center on return2092 * \param *a first point2093 * \param *b second point2094 * \param *c third point2095 */2096 void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c)2097 {2098 Vector helper;2099 double alpha, beta, gamma;2100 Vector SideA, SideB, SideC;2101 SideA.CopyVector(b);2102 SideA.SubtractVector(c);2103 SideB.CopyVector(c);2104 SideB.SubtractVector(a);2105 SideC.CopyVector(a);2106 SideC.SubtractVector(b);2107 alpha = M_PI - SideB.Angle(&SideC);2108 beta = M_PI - SideC.Angle(&SideA);2109 gamma = M_PI - SideA.Angle(&SideB);2110 //cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;2111 if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)2112 cerr << "GetCenterofCircumcircle: Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;2113 2114 Center->Zero();2115 helper.CopyVector(a);2116 helper.Scale(sin(2.*alpha));2117 Center->AddVector(&helper);2118 helper.CopyVector(b);2119 helper.Scale(sin(2.*beta));2120 Center->AddVector(&helper);2121 helper.CopyVector(c);2122 helper.Scale(sin(2.*gamma));2123 Center->AddVector(&helper);2124 Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));2125 };2126 2127 /** Returns the parameter "path length" for a given \a NewSphereCenter relative to \a OldSphereCenter on a circle on the plane \a CirclePlaneNormal with center \a CircleCenter and radius \a CircleRadius.2128 * Test whether the \a NewSphereCenter is really on the given plane and in distance \a CircleRadius from \a CircleCenter.2129 * It calculates the angle, making it unique on [0,2.*M_PI) by comparing to SearchDirection.2130 * Also the new center is invalid if it the same as the old one and does not lie right above (\a NormalVector) the base line (\a CircleCenter).2131 * \param CircleCenter Center of the parameter circle2132 * \param CirclePlaneNormal normal vector to plane of the parameter circle2133 * \param CircleRadius radius of the parameter circle2134 * \param NewSphereCenter new center of a circumcircle2135 * \param OldSphereCenter old center of a circumcircle, defining the zero "path length" on the parameter circle2136 * \param NormalVector normal vector2137 * \param SearchDirection search direction to make angle unique on return.2138 * \return Angle between \a NewSphereCenter and \a OldSphereCenter relative to \a CircleCenter, 2.*M_PI if one test fails2139 */2140 double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection)2141 {2142 Vector helper;2143 double radius, alpha;2144 2145 helper.CopyVector(&NewSphereCenter);2146 // test whether new center is on the parameter circle's plane2147 if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {2148 cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;2149 helper.ProjectOntoPlane(&CirclePlaneNormal);2150 }2151 radius = helper.ScalarProduct(&helper);2152 // test whether the new center vector has length of CircleRadius2153 if (fabs(radius - CircleRadius) > HULLEPSILON)2154 cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;2155 alpha = helper.Angle(&OldSphereCenter);2156 // make the angle unique by checking the halfplanes/search direction2157 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON) // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals2158 alpha = 2.*M_PI - alpha;2159 //cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;2160 radius = helper.Distance(&OldSphereCenter);2161 helper.ProjectOntoPlane(&NormalVector);2162 // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles2163 if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {2164 //cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;2165 return alpha;2166 } else {2167 //cout << Verbose(1) << "INFO: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;2168 return 2.*M_PI;2169 }2170 };2171 2172 2173 /** Checks whether the triangle consisting of the three atoms is already present.2174 * Searches for the points in Tesselation::PointsOnBoundary and checks their2175 * lines. If any of the three edges already has two triangles attached, false is2176 * returned.2177 * \param *out output stream for debugging2178 * \param *Candidates endpoints of the triangle candidate2179 * \return integer 0 if no triangle exists, 1 if one triangle exists, 2 if two2180 * triangles exist which is the maximum for three points2181 */2182 int Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) {2183 LineMap::iterator FindLine;2184 PointMap::iterator FindPoint;2185 TriangleMap::iterator FindTriangle;2186 int adjacentTriangleCount = 0;2187 class BoundaryPointSet *Points[3];2188 2189 //*out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;2190 // builds a triangle point set (Points) of the end points2191 for (int i = 0; i < 3; i++) {2192 FindPoint = PointsOnBoundary.find(Candidates[i]->nr);2193 if (FindPoint != PointsOnBoundary.end()) {2194 Points[i] = FindPoint->second;2195 } else {2196 Points[i] = NULL;2197 }2198 }2199 2200 // checks lines between the points in the Points for their adjacent triangles2201 for (int i = 0; i < 3; i++) {2202 if (Points[i] != NULL) {2203 for (int j = i; j < 3; j++) {2204 if (Points[j] != NULL) {2205 FindLine = Points[i]->lines.find(Points[j]->node->nr);2206 if (FindLine != Points[i]->lines.end()) {2207 for (; FindLine->first == Points[j]->node->nr; FindLine++) {2208 FindTriangle = FindLine->second->triangles.begin();2209 for (; FindTriangle != FindLine->second->triangles.end(); FindTriangle++) {2210 if ((2211 (FindTriangle->second->endpoints[0] == Points[0])2212 || (FindTriangle->second->endpoints[0] == Points[1])2213 || (FindTriangle->second->endpoints[0] == Points[2])2214 ) && (2215 (FindTriangle->second->endpoints[1] == Points[0])2216 || (FindTriangle->second->endpoints[1] == Points[1])2217 || (FindTriangle->second->endpoints[1] == Points[2])2218 ) && (2219 (FindTriangle->second->endpoints[2] == Points[0])2220 || (FindTriangle->second->endpoints[2] == Points[1])2221 || (FindTriangle->second->endpoints[2] == Points[2])2222 )2223 ) {2224 adjacentTriangleCount++;2225 }2226 }2227 }2228 // Only one of the triangle lines must be considered for the triangle count.2229 *out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;2230 return adjacentTriangleCount;2231 2232 }2233 }2234 }2235 }2236 }2237 2238 *out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;2239 return adjacentTriangleCount;2240 };2241 2242 /** This recursive function finds a third point, to form a triangle with two given ones.2243 * Note that this function is for the starting triangle.2244 * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points2245 * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then2246 * the center of the sphere is still fixed up to a single parameter. The band of possible values2247 * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives2248 * us the "null" on this circle, the new center of the candidate point will be some way along this2249 * circle. The shorter the way the better is the candidate. Note that the direction is clearly given2250 * by the normal vector of the base triangle that always points outwards by construction.2251 * Hence, we construct a Center of this circle which sits right in the middle of the current base line.2252 * We construct the normal vector that defines the plane this circle lies in, it is just in the2253 * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest2254 * with respect to the length of the baseline and the sphere's fixed \a RADIUS.2255 * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center2256 * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check2257 * both.2258 * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check2259 * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check2260 * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal2261 * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality2262 * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether2263 * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI).2264 * @param NormalVector normal direction of the base triangle (here the unit axis vector, \sa Find_starting_triangle())2265 * @param SearchDirection general direction where to search for the next point, relative to center of BaseLine2266 * @param OldSphereCenter center of sphere for base triangle, relative to center of BaseLine, giving null angle for the parameter circle2267 * @param BaseLine BoundaryLineSet with the current base line2268 * @param ThirdNode third atom to avoid in search2269 * @param candidates list of equally good candidates to return2270 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate2271 * @param RADIUS radius of sphere2272 * @param *LC LinkedCell structure with neighbouring atoms2273 */2274 void Find_third_point_for_Tesselation(2275 Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter,2276 class BoundaryLineSet *BaseLine, atom *ThirdNode, CandidateList* &candidates,2277 double *ShortestAngle, const double RADIUS, LinkedCell *LC2278 ) {2279 Vector CircleCenter; // center of the circle, i.e. of the band of sphere's centers2280 Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in2281 Vector SphereCenter;2282 Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility2283 Vector OtherNewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility2284 Vector NewNormalVector; // normal vector of the Candidate's triangle2285 Vector helper, OptCandidateCenter, OtherOptCandidateCenter;2286 LinkedAtoms *List = NULL;2287 double CircleRadius; // radius of this circle2288 double radius;2289 double alpha, Otheralpha; // angles (i.e. parameter for the circle).2290 int N[NDIM], Nlower[NDIM], Nupper[NDIM];2291 atom *Candidate = NULL;2292 CandidateForTesselation *optCandidate = NULL;2293 2294 cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;2295 2296 //cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;2297 2298 // construct center of circle2299 CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));2300 CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);2301 CircleCenter.Scale(0.5);2302 2303 // construct normal vector of circle2304 CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);2305 CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);2306 2307 // calculate squared radius atom *ThirdNode,f circle2308 radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);2309 if (radius/4. < RADIUS*RADIUS) {2310 CircleRadius = RADIUS*RADIUS - radius/4.;2311 CirclePlaneNormal.Normalize();2312 //cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;2313 2314 // test whether old center is on the band's plane2315 if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {2316 cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;2317 OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);2318 }2319 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);2320 if (fabs(radius - CircleRadius) < HULLEPSILON) {2321 2322 // check SearchDirection2323 //cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;2324 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) { // rotated the wrong way!2325 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;2326 }2327 2328 // get cell for the starting atom2329 if (LC->SetIndexToVector(&CircleCenter)) {2330 for(int i=0;i<NDIM;i++) // store indices of this cell2331 N[i] = LC->n[i];2332 //cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;2333 } else {2334 cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;2335 return;2336 }2337 // then go through the current and all neighbouring cells and check the contained atoms for possible candidates2338 //cout << Verbose(2) << "LC Intervals:";2339 for (int i=0;i<NDIM;i++) {2340 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;2341 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;2342 //cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";2343 }2344 //cout << endl;2345 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)2346 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)2347 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {2348 List = LC->GetCurrentCell();2349 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;2350 if (List != NULL) {2351 for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {2352 Candidate = (*Runner);2353 2354 // check for three unique points2355 //cout << Verbose(2) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;2356 if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) ){2357 2358 // construct both new centers2359 GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));2360 OtherNewSphereCenter.CopyVector(&NewSphereCenter);2361 2362 if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)))2363 && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)2364 ) {2365 helper.CopyVector(&NewNormalVector);2366 //cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;2367 radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);2368 if (radius < RADIUS*RADIUS) {2369 helper.Scale(sqrt(RADIUS*RADIUS - radius));2370 //cout << Verbose(2) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << " with sphere radius " << RADIUS << "." << endl;2371 NewSphereCenter.AddVector(&helper);2372 NewSphereCenter.SubtractVector(&CircleCenter);2373 //cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;2374 2375 // OtherNewSphereCenter is created by the same vector just in the other direction2376 helper.Scale(-1.);2377 OtherNewSphereCenter.AddVector(&helper);2378 OtherNewSphereCenter.SubtractVector(&CircleCenter);2379 //cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;2380 2381 alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);2382 Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);2383 alpha = min(alpha, Otheralpha);2384 // if there is a better candidate, drop the current list and add the new candidate2385 // otherwise ignore the new candidate and keep the list2386 if (*ShortestAngle > (alpha - HULLEPSILON)) {2387 optCandidate = new CandidateForTesselation(Candidate, BaseLine, OptCandidateCenter, OtherOptCandidateCenter);2388 if (fabs(alpha - Otheralpha) > MYEPSILON) {2389 optCandidate->OptCenter.CopyVector(&NewSphereCenter);2390 optCandidate->OtherOptCenter.CopyVector(&OtherNewSphereCenter);2391 } else {2392 optCandidate->OptCenter.CopyVector(&OtherNewSphereCenter);2393 optCandidate->OtherOptCenter.CopyVector(&NewSphereCenter);2394 }2395 // if there is an equal candidate, add it to the list without clearing the list2396 if ((*ShortestAngle - HULLEPSILON) < alpha) {2397 candidates->push_back(optCandidate);2398 cout << Verbose(2) << "ACCEPT: We have found an equally good candidate: " << *(optCandidate->point) << " with "2399 << alpha << " and circumsphere's center at " << optCandidate->OptCenter << "." << endl;2400 } else {2401 // remove all candidates from the list and then the list itself2402 class CandidateForTesselation *remover = NULL;2403 for (CandidateList::iterator it = candidates->begin(); it != candidates->end(); ++it) {2404 remover = *it;2405 delete(remover);2406 }2407 candidates->clear();2408 candidates->push_back(optCandidate);2409 cout << Verbose(2) << "ACCEPT: We have found a better candidate: " << *(optCandidate->point) << " with "2410 << alpha << " and circumsphere's center at " << optCandidate->OptCenter << "." << endl;2411 }2412 *ShortestAngle = alpha;2413 //cout << Verbose(2) << "INFO: There are " << candidates->size() << " candidates in the list now." << endl;2414 } else {2415 if ((optCandidate != NULL) && (optCandidate->point != NULL)) {2416 //cout << Verbose(2) << "REJECT: Old candidate: " << *(optCandidate->point) << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;2417 } else {2418 //cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;2419 }2420 }2421 2422 } else {2423 //cout << Verbose(2) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;2424 }2425 } else {2426 //cout << Verbose(2) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;2427 }2428 } else {2429 if (ThirdNode != NULL) {2430 //cout << Verbose(2) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;2431 } else {2432 //cout << Verbose(2) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;2433 }2434 }2435 }2436 }2437 }2438 } else {2439 cerr << Verbose(2) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;2440 }2441 } else {2442 if (ThirdNode != NULL)2443 cout << Verbose(2) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;2444 else2445 cout << Verbose(2) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;2446 }2447 2448 //cout << Verbose(2) << "INFO: Sorting candidate list ..." << endl;2449 if (candidates->size() > 1) {2450 candidates->unique();2451 candidates->sort(sortCandidates);2452 }2453 2454 cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;2455 };2456 2457 struct Intersection {2458 Vector x1;2459 Vector x2;2460 Vector x3;2461 Vector x4;2462 };2463 2464 /**2465 * Intersection calculation function.2466 *2467 * @param x to find the result for2468 * @param function parameter2469 */2470 double MinIntersectDistance(const gsl_vector * x, void *params) {2471 double retval = 0;2472 struct Intersection *I = (struct Intersection *)params;2473 Vector intersection;2474 Vector SideA,SideB,HeightA, HeightB;2475 for (int i=0;i<NDIM;i++)2476 intersection.x[i] = gsl_vector_get(x, i);2477 2478 SideA.CopyVector(&(I->x1));2479 SideA.SubtractVector(&I->x2);2480 HeightA.CopyVector(&intersection);2481 HeightA.SubtractVector(&I->x1);2482 HeightA.ProjectOntoPlane(&SideA);2483 2484 SideB.CopyVector(&I->x3);2485 SideB.SubtractVector(&I->x4);2486 HeightB.CopyVector(&intersection);2487 HeightB.SubtractVector(&I->x3);2488 HeightB.ProjectOntoPlane(&SideB);2489 2490 retval = HeightA.ScalarProduct(&HeightA) + HeightB.ScalarProduct(&HeightB);2491 //cout << Verbose(2) << "MinIntersectDistance called, result: " << retval << endl;2492 2493 return retval;2494 };2495 2496 2497 /**2498 * Calculates whether there is an intersection between two lines. The first line2499 * always goes through point 1 and point 2 and the second line is given by the2500 * connection between point 4 and point 5.2501 *2502 * @param point 1 of line 12503 * @param point 2 of line 12504 * @param point 1 of line 22505 * @param point 2 of line 22506 *2507 * @return true if there is an intersection between the given lines, false otherwise2508 */2509 bool existsIntersection(Vector point1, Vector point2, Vector point3, Vector point4) {2510 bool result;2511 2512 struct Intersection par;2513 par.x1.CopyVector(&point1);2514 par.x2.CopyVector(&point2);2515 par.x3.CopyVector(&point3);2516 par.x4.CopyVector(&point4);2517 2518 const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;2519 gsl_multimin_fminimizer *s = NULL;2520 gsl_vector *ss, *x;2521 gsl_multimin_function minex_func;2522 2523 size_t iter = 0;2524 int status;2525 double size;2526 2527 /* Starting point */2528 x = gsl_vector_alloc(NDIM);2529 gsl_vector_set(x, 0, point1.x[0]);2530 gsl_vector_set(x, 1, point1.x[1]);2531 gsl_vector_set(x, 2, point1.x[2]);2532 2533 /* Set initial step sizes to 1 */2534 ss = gsl_vector_alloc(NDIM);2535 gsl_vector_set_all(ss, 1.0);2536 2537 /* Initialize method and iterate */2538 minex_func.n = NDIM;2539 minex_func.f = &MinIntersectDistance;2540 minex_func.params = (void *)∥2541 2542 s = gsl_multimin_fminimizer_alloc(T, NDIM);2543 gsl_multimin_fminimizer_set(s, &minex_func, x, ss);2544 2545 do {2546 iter++;2547 status = gsl_multimin_fminimizer_iterate(s);2548 2549 if (status) {2550 break;2551 }2552 2553 size = gsl_multimin_fminimizer_size(s);2554 status = gsl_multimin_test_size(size, 1e-2);2555 2556 if (status == GSL_SUCCESS) {2557 cout << Verbose(2) << "converged to minimum" << endl;2558 }2559 } while (status == GSL_CONTINUE && iter < 100);2560 2561 // check whether intersection is in between or not2562 Vector intersection, SideA, SideB, HeightA, HeightB;2563 double t1, t2;2564 for (int i = 0; i < NDIM; i++) {2565 intersection.x[i] = gsl_vector_get(s->x, i);2566 }2567 2568 SideA.CopyVector(&par.x2);2569 SideA.SubtractVector(&par.x1);2570 HeightA.CopyVector(&intersection);2571 HeightA.SubtractVector(&par.x1);2572 2573 t1 = HeightA.Projection(&SideA)/SideA.ScalarProduct(&SideA);2574 2575 SideB.CopyVector(&par.x4);2576 SideB.SubtractVector(&par.x3);2577 HeightB.CopyVector(&intersection);2578 HeightB.SubtractVector(&par.x3);2579 2580 t2 = HeightB.Projection(&SideB)/SideB.ScalarProduct(&SideB);2581 2582 cout << Verbose(2) << "Intersection " << intersection << " is at "2583 << t1 << " for (" << point1 << "," << point2 << ") and at "2584 << t2 << " for (" << point3 << "," << point4 << "): ";2585 2586 if (((t1 >= 0) && (t1 <= 1)) && ((t2 >= 0) && (t2 <= 1))) {2587 cout << "true intersection." << endl;2588 result = true;2589 } else {2590 cout << "intersection out of region of interest." << endl;2591 result = false;2592 }2593 2594 // free minimizer stuff2595 gsl_vector_free(x);2596 gsl_vector_free(ss);2597 gsl_multimin_fminimizer_free(s);2598 2599 return result;2600 }2601 2602 /** Finds the second point of starting triangle.2603 * \param *a first atom2604 * \param *Candidate pointer to candidate atom on return2605 * \param Oben vector indicating the outside2606 * \param Opt_Candidate reference to recommended candidate on return2607 * \param Storage[3] array storing angles and other candidate information2608 * \param RADIUS radius of virtual sphere2609 * \param *LC LinkedCell structure with neighbouring atoms2610 */2611 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC)2612 {2613 cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;2614 Vector AngleCheck;2615 double norm = -1., angle;2616 LinkedAtoms *List = NULL;2617 int N[NDIM], Nlower[NDIM], Nupper[NDIM];2618 2619 if (LC->SetIndexToAtom(a)) { // get cell for the starting atom2620 for(int i=0;i<NDIM;i++) // store indices of this cell2621 N[i] = LC->n[i];2622 } else {2623 cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;2624 return;2625 }2626 // then go through the current and all neighbouring cells and check the contained atoms for possible candidates2627 cout << Verbose(3) << "LC Intervals from [";2628 for (int i=0;i<NDIM;i++) {2629 cout << " " << N[i] << "<->" << LC->N[i];2630 }2631 cout << "] :";2632 for (int i=0;i<NDIM;i++) {2633 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;2634 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;2635 cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";2636 }2637 cout << endl;2638 2639 2640 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)2641 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)2642 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {2643 List = LC->GetCurrentCell();2644 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;2645 if (List != NULL) {2646 for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {2647 Candidate = (*Runner);2648 // check if we only have one unique point yet ...2649 if (a != Candidate) {2650 // Calculate center of the circle with radius RADIUS through points a and Candidate2651 Vector OrthogonalizedOben, a_Candidate, Center;2652 double distance, scaleFactor;2653 2654 OrthogonalizedOben.CopyVector(&Oben);2655 a_Candidate.CopyVector(&(a->x));2656 a_Candidate.SubtractVector(&(Candidate->x));2657 OrthogonalizedOben.ProjectOntoPlane(&a_Candidate);2658 OrthogonalizedOben.Normalize();2659 distance = 0.5 * a_Candidate.Norm();2660 scaleFactor = sqrt(((RADIUS * RADIUS) - (distance * distance)));2661 OrthogonalizedOben.Scale(scaleFactor);2662 2663 Center.CopyVector(&(Candidate->x));2664 Center.AddVector(&(a->x));2665 Center.Scale(0.5);2666 Center.AddVector(&OrthogonalizedOben);2667 2668 AngleCheck.CopyVector(&Center);2669 AngleCheck.SubtractVector(&(a->x));2670 norm = a_Candidate.Norm();2671 // second point shall have smallest angle with respect to Oben vector2672 if (norm < RADIUS*2.) {2673 angle = AngleCheck.Angle(&Oben);2674 if (angle < Storage[0]) {2675 //cout << Verbose(3) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);2676 cout << Verbose(3) << "Current candidate is " << *Candidate << ": Is a better candidate with distance " << norm << " and angle " << angle << " to oben " << Oben << ".\n";2677 Opt_Candidate = Candidate;2678 Storage[0] = angle;2679 //cout << Verbose(3) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);2680 } else {2681 //cout << Verbose(3) << "Current candidate is " << *Candidate << ": Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;2682 }2683 } else {2684 //cout << Verbose(3) << "Current candidate is " << *Candidate << ": Refused due to Radius " << norm << endl;2685 }2686 } else {2687 //cout << Verbose(3) << "Current candidate is " << *Candidate << ": Candidate is equal to first endpoint." << *a << "." << endl;2688 }2689 }2690 } else {2691 cout << Verbose(3) << "Linked cell list is empty." << endl;2692 }2693 }2694 cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;2695 };2696 2697 /** Finds the starting triangle for find_non_convex_border().2698 * Looks at the outermost atom per axis, then Find_second_point_for_Tesselation()2699 * for the second and Find_next_suitable_point_via_Angle_of_Sphere() for the third2700 * point are called.2701 * \param RADIUS radius of virtual rolling sphere2702 * \param *LC LinkedCell structure with neighbouring atoms2703 */2704 void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC)2705 {2706 cout << Verbose(1) << "Begin of Find_starting_triangle\n";2707 int i = 0;2708 LinkedAtoms *List = NULL;2709 atom* FirstPoint = NULL;2710 atom* SecondPoint = NULL;2711 atom* MaxAtom[NDIM];2712 double max_coordinate[NDIM];2713 Vector Oben;2714 Vector helper;2715 Vector Chord;2716 Vector SearchDirection;2717 2718 Oben.Zero();2719 2720 for (i = 0; i < 3; i++) {2721 MaxAtom[i] = NULL;2722 max_coordinate[i] = -1;2723 }2724 2725 // 1. searching topmost atom with respect to each axis2726 for (int i=0;i<NDIM;i++) { // each axis2727 LC->n[i] = LC->N[i]-1; // current axis is topmost cell2728 for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)2729 for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {2730 List = LC->GetCurrentCell();2731 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;2732 if (List != NULL) {2733 for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {2734 if ((*Runner)->x.x[i] > max_coordinate[i]) {2735 cout << Verbose(2) << "New maximal for axis " << i << " atom is " << *(*Runner) << " at " << (*Runner)->x << "." << endl;2736 max_coordinate[i] = (*Runner)->x.x[i];2737 MaxAtom[i] = (*Runner);2738 }2739 }2740 } else {2741 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;2742 }2743 }2744 }2745 2746 cout << Verbose(2) << "Found maximum coordinates: ";2747 for (int i=0;i<NDIM;i++)2748 cout << i << ": " << *MaxAtom[i] << "\t";2749 cout << endl;2750 2751 BTS = NULL;2752 CandidateList *Opt_Candidates = new CandidateList();2753 for (int k=0;k<NDIM;k++) {2754 Oben.x[k] = 1.;2755 FirstPoint = MaxAtom[k];2756 cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;2757 2758 double ShortestAngle;2759 atom* Opt_Candidate = NULL;2760 ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.2761 2762 Find_second_point_for_Tesselation(FirstPoint, NULL, Oben, Opt_Candidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...2763 SecondPoint = Opt_Candidate;2764 if (SecondPoint == NULL) // have we found a second point?2765 continue;2766 else2767 cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";2768 2769 helper.CopyVector(&(FirstPoint->x));2770 helper.SubtractVector(&(SecondPoint->x));2771 helper.Normalize();2772 Oben.ProjectOntoPlane(&helper);2773 Oben.Normalize();2774 helper.VectorProduct(&Oben);2775 ShortestAngle = 2.*M_PI; // This will indicate the quadrant.2776 2777 Chord.CopyVector(&(FirstPoint->x)); // bring into calling function2778 Chord.SubtractVector(&(SecondPoint->x));2779 double radius = Chord.ScalarProduct(&Chord);2780 double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);2781 helper.CopyVector(&Oben);2782 helper.Scale(CircleRadius);2783 // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)2784 2785 // look in one direction of baseline for initial candidate2786 SearchDirection.MakeNormalVector(&Chord, &Oben); // whether we look "left" first or "right" first is not important ...2787 2788 // adding point 1 and point 2 and the line between them2789 AddTrianglePoint(FirstPoint, 0);2790 AddTrianglePoint(SecondPoint, 1);2791 AddTriangleLine(TPS[0], TPS[1], 0);2792 2793 //cout << Verbose(2) << "INFO: OldSphereCenter is at " << helper << ".\n";2794 Find_third_point_for_Tesselation(2795 Oben, SearchDirection, helper, BLS[0], NULL, *&Opt_Candidates, &ShortestAngle, RADIUS, LC2796 );2797 cout << Verbose(1) << "List of third Points is ";2798 for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {2799 cout << " " << *(*it)->point;2800 }2801 cout << endl;2802 2803 for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {2804 // add third triangle point2805 AddTrianglePoint((*it)->point, 2);2806 // add the second and third line2807 AddTriangleLine(TPS[1], TPS[2], 1);2808 AddTriangleLine(TPS[0], TPS[2], 2);2809 // ... and triangles to the Maps of the Tesselation class2810 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);2811 AddTriangle();2812 // ... and calculate its normal vector (with correct orientation)2813 (*it)->OptCenter.Scale(-1.);2814 cout << Verbose(2) << "Anti-Oben is currently " << (*it)->OptCenter << "." << endl;2815 BTS->GetNormalVector((*it)->OptCenter); // vector to compare with should point inwards2816 cout << Verbose(0) << "==> Found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and "2817 << *(*it)->point << " with normal vector " << BTS->NormalVector << ".\n";2818 2819 // if we do not reach the end with the next step of iteration, we need to setup a new first line2820 if (it != Opt_Candidates->end()--) {2821 FirstPoint = (*it)->BaseLine->endpoints[0]->node;2822 SecondPoint = (*it)->point;2823 // adding point 1 and point 2 and the line between them2824 AddTrianglePoint(FirstPoint, 0);2825 AddTrianglePoint(SecondPoint, 1);2826 AddTriangleLine(TPS[0], TPS[1], 0);2827 }2828 cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;2829 }2830 if (BTS != NULL) // we have created one starting triangle2831 break;2832 else {2833 // remove all candidates from the list and then the list itself2834 class CandidateForTesselation *remover = NULL;2835 for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {2836 remover = *it;2837 delete(remover);2838 }2839 Opt_Candidates->clear();2840 }2841 }2842 2843 // remove all candidates from the list and then the list itself2844 class CandidateForTesselation *remover = NULL;2845 for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {2846 remover = *it;2847 delete(remover);2848 }2849 delete(Opt_Candidates);2850 cout << Verbose(1) << "End of Find_starting_triangle\n";2851 };2852 2853 /** Checks for a new special triangle whether one of its edges is already present with one one triangle connected.2854 * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not2855 * make it bigger (i.e. closing one (the baseline) and opening two new ones).2856 * \param TPS[3] nodes of the triangle2857 * \return true - there is such a line (i.e. creation of degenerated triangle is valid), false - no such line (don't create)2858 */2859 bool CheckLineCriteriaforDegeneratedTriangle(class BoundaryPointSet *nodes[3])2860 {2861 bool result = false;2862 int counter = 0;2863 2864 // check all three points2865 for (int i=0;i<3;i++)2866 for (int j=i+1; j<3; j++) {2867 if (nodes[i]->lines.find(nodes[j]->node->nr) != nodes[i]->lines.end()) { // there already is a line2868 LineMap::iterator FindLine;2869 pair<LineMap::iterator,LineMap::iterator> FindPair;2870 FindPair = nodes[i]->lines.equal_range(nodes[j]->node->nr);2871 for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {2872 // If there is a line with less than two attached triangles, we don't need a new line.2873 if (FindLine->second->TrianglesCount < 2) {2874 counter++;2875 break; // increase counter only once per edge2876 }2877 }2878 } else { // no line2879 cout << Verbose(1) << "ERROR: The line between " << nodes[i] << " and " << nodes[j] << " is not yet present, hence no need for a degenerate triangle!" << endl;2880 result = true;2881 }2882 }2883 if (counter > 1) {2884 cout << Verbose(2) << "INFO: Degenerate triangle is ok, at least two, here " << counter << ", existing lines are used." << endl;2885 result = true;2886 }2887 return result;2888 };2889 2890 2891 /** This function finds a triangle to a line, adjacent to an existing one.2892 * @param out output stream for debugging2893 * @param *mol molecule with Atom's and Bond's2894 * @param Line current baseline to search from2895 * @param T current triangle which \a Line is edge of2896 * @param RADIUS radius of the rolling ball2897 * @param N number of found triangles2898 * @param *filename filename base for intermediate envelopes2899 * @param *LC LinkedCell structure with neighbouring atoms2900 */2901 bool Tesselation::Find_next_suitable_triangle(ofstream *out,2902 molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,2903 const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)2904 {2905 cout << Verbose(0) << "Begin of Find_next_suitable_triangle\n";2906 ofstream *tempstream = NULL;2907 char NumberName[255];2908 bool result = true;2909 CandidateList *Opt_Candidates = new CandidateList();2910 2911 Vector CircleCenter;2912 Vector CirclePlaneNormal;2913 Vector OldSphereCenter;2914 Vector SearchDirection;2915 Vector helper;2916 atom *ThirdNode = NULL;2917 LineMap::iterator testline;2918 double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.2919 double radius, CircleRadius;2920 2921 cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;2922 for (int i=0;i<3;i++)2923 if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))2924 ThirdNode = T.endpoints[i]->node;2925 2926 // construct center of circle2927 CircleCenter.CopyVector(&Line.endpoints[0]->node->x);2928 CircleCenter.AddVector(&Line.endpoints[1]->node->x);2929 CircleCenter.Scale(0.5);2930 2931 // construct normal vector of circle2932 CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);2933 CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);2934 2935 // calculate squared radius of circle2936 radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);2937 if (radius/4. < RADIUS*RADIUS) {2938 CircleRadius = RADIUS*RADIUS - radius/4.;2939 CirclePlaneNormal.Normalize();2940 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;2941 2942 // construct old center2943 GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));2944 helper.CopyVector(&T.NormalVector); // normal vector ensures that this is correct center of the two possible ones2945 radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);2946 helper.Scale(sqrt(RADIUS*RADIUS - radius));2947 OldSphereCenter.AddVector(&helper);2948 OldSphereCenter.SubtractVector(&CircleCenter);2949 //cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;2950 2951 // construct SearchDirection2952 SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);2953 helper.CopyVector(&Line.endpoints[0]->node->x);2954 helper.SubtractVector(&ThirdNode->x);2955 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)// ohoh, SearchDirection points inwards!2956 SearchDirection.Scale(-1.);2957 SearchDirection.ProjectOntoPlane(&OldSphereCenter);2958 SearchDirection.Normalize();2959 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;2960 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {2961 // rotated the wrong way!2962 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;2963 }2964 2965 // add third point2966 Find_third_point_for_Tesselation(2967 T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidates,2968 &ShortestAngle, RADIUS, LC2969 );2970 2971 } else {2972 cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;2973 }2974 2975 if (Opt_Candidates->begin() == Opt_Candidates->end()) {2976 cerr << "WARNING: Could not find a suitable candidate." << endl;2977 return false;2978 }2979 cout << Verbose(1) << "Third Points are ";2980 for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {2981 cout << " " << *(*it)->point;2982 }2983 cout << endl;2984 2985 BoundaryLineSet *BaseRay = &Line;2986 for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {2987 cout << Verbose(1) << " Third point candidate is " << *(*it)->point2988 << " with circumsphere's center at " << (*it)->OptCenter << "." << endl;2989 cout << Verbose(1) << " Baseline is " << *BaseRay << endl;2990 2991 // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)2992 atom *AtomCandidates[3];2993 AtomCandidates[0] = (*it)->point;2994 AtomCandidates[1] = BaseRay->endpoints[0]->node;2995 AtomCandidates[2] = BaseRay->endpoints[1]->node;2996 int existentTrianglesCount = CheckPresenceOfTriangle(out, AtomCandidates);2997 2998 BTS = NULL;2999 // If there is no triangle, add it regularly.3000 if (existentTrianglesCount == 0) {3001 AddTrianglePoint((*it)->point, 0);3002 AddTrianglePoint(BaseRay->endpoints[0]->node, 1);3003 AddTrianglePoint(BaseRay->endpoints[1]->node, 2);3004 3005 AddTriangleLine(TPS[0], TPS[1], 0);3006 AddTriangleLine(TPS[0], TPS[2], 1);3007 AddTriangleLine(TPS[1], TPS[2], 2);3008 3009 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);3010 AddTriangle();3011 (*it)->OptCenter.Scale(-1.);3012 BTS->GetNormalVector((*it)->OptCenter);3013 (*it)->OptCenter.Scale(-1.);3014 3015 cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector3016 << " for this triangle ... " << endl;3017 //cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << *BaseRay << "." << endl;3018 } else if (existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time.3019 AddTrianglePoint((*it)->point, 0);3020 AddTrianglePoint(BaseRay->endpoints[0]->node, 1);3021 AddTrianglePoint(BaseRay->endpoints[1]->node, 2);3022 3023 // We demand that at most one new degenerate line is created and that this line also already exists (which has to be the case due to existentTrianglesCount == 1)3024 // i.e. at least one of the three lines must be present with TriangleCount <= 13025 if (CheckLineCriteriaforDegeneratedTriangle(TPS)) {3026 AddTriangleLine(TPS[0], TPS[1], 0);3027 AddTriangleLine(TPS[0], TPS[2], 1);3028 AddTriangleLine(TPS[1], TPS[2], 2);3029 3030 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);3031 AddTriangle();3032 3033 (*it)->OtherOptCenter.Scale(-1.);3034 BTS->GetNormalVector((*it)->OtherOptCenter);3035 (*it)->OtherOptCenter.Scale(-1.);3036 3037 cout << "--> WARNING: Special new triangle with " << *BTS << " and normal vector " << BTS->NormalVector3038 << " for this triangle ... " << endl;3039 cout << Verbose(1) << "We have "<< BaseRay->TrianglesCount << " for line " << BaseRay << "." << endl;3040 } else {3041 cout << Verbose(1) << "WARNING: This triangle consisting of ";3042 cout << *(*it)->point << ", ";3043 cout << *BaseRay->endpoints[0]->node << " and ";3044 cout << *BaseRay->endpoints[1]->node << " ";3045 cout << "exists and is not added, as it does not seem helpful!" << endl;3046 result = false;3047 }3048 } else {3049 cout << Verbose(1) << "This triangle consisting of ";3050 cout << *(*it)->point << ", ";3051 cout << *BaseRay->endpoints[0]->node << " and ";3052 cout << *BaseRay->endpoints[1]->node << " ";3053 cout << "is invalid!" << endl;3054 result = false;3055 }3056 3057 if ((result) && (existentTrianglesCount < 2) && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 1 == 0))) { // if we have a new triangle and want to output each new triangle configuration3058 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);3059 if (DoTecplotOutput) {3060 string NameofTempFile(tempbasename);3061 NameofTempFile.append(NumberName);3062 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))3063 NameofTempFile.erase(npos, 1);3064 NameofTempFile.append(TecplotSuffix);3065 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";3066 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);3067 write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);3068 tempstream->close();3069 tempstream->flush();3070 delete(tempstream);3071 }3072 3073 if (DoRaster3DOutput) {3074 string NameofTempFile(tempbasename);3075 NameofTempFile.append(NumberName);3076 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))3077 NameofTempFile.erase(npos, 1);3078 NameofTempFile.append(Raster3DSuffix);3079 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";3080 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);3081 write_raster3d_file(out, tempstream, this, mol);3082 // include the current position of the virtual sphere in the temporary raster3d file3083 // make the circumsphere's center absolute again3084 helper.CopyVector(&BaseRay->endpoints[0]->node->x);3085 helper.AddVector(&BaseRay->endpoints[1]->node->x);3086 helper.Scale(0.5);3087 (*it)->OptCenter.AddVector(&helper);3088 Vector *center = mol->DetermineCenterOfAll(out);3089 (*it)->OptCenter.SubtractVector(center);3090 delete(center);3091 // and add to file plus translucency object3092 *tempstream << "# current virtual sphere\n";3093 *tempstream << "8\n 25.0 0.6 -1.0 -1.0 -1.0 0.2 0 0 0 0\n";3094 *tempstream << "2\n " << (*it)->OptCenter.x[0] << " "3095 << (*it)->OptCenter.x[1] << " " << (*it)->OptCenter.x[2]3096 << "\t" << RADIUS << "\t1 0 0\n";3097 *tempstream << "9\n terminating special property\n";3098 tempstream->close();3099 tempstream->flush();3100 delete(tempstream);3101 }3102 if (DoTecplotOutput || DoRaster3DOutput)3103 TriangleFilesWritten++;3104 }3105 3106 // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point))3107 BaseRay = BLS[0];3108 }3109 3110 // remove all candidates from the list and then the list itself3111 class CandidateForTesselation *remover = NULL;3112 for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {3113 remover = *it;3114 delete(remover);3115 }3116 delete(Opt_Candidates);3117 cout << Verbose(0) << "End of Find_next_suitable_triangle\n";3118 return result;3119 };3120 3121 /**3122 * Sort function for the candidate list.3123 */3124 bool sortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2) {3125 Vector BaseLineVector, OrthogonalVector, helper;3126 if (candidate1->BaseLine != candidate2->BaseLine) { // sanity check3127 cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;3128 //return false;3129 exit(1);3130 }3131 // create baseline vector3132 BaseLineVector.CopyVector(&(candidate1->BaseLine->endpoints[1]->node->x));3133 BaseLineVector.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));3134 BaseLineVector.Normalize();3135 3136 // create normal in-plane vector to cope with acos() non-uniqueness on [0,2pi] (note that is pointing in the "right" direction already, hence ">0" test!)3137 helper.CopyVector(&(candidate1->BaseLine->endpoints[0]->node->x));3138 helper.SubtractVector(&(candidate1->point->x));3139 OrthogonalVector.CopyVector(&helper);3140 helper.VectorProduct(&BaseLineVector);3141 OrthogonalVector.SubtractVector(&helper);3142 OrthogonalVector.Normalize();3143 3144 // calculate both angles and correct with in-plane vector3145 helper.CopyVector(&(candidate1->point->x));3146 helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));3147 double phi = BaseLineVector.Angle(&helper);3148 if (OrthogonalVector.ScalarProduct(&helper) > 0) {3149 phi = 2.*M_PI - phi;3150 }3151 helper.CopyVector(&(candidate2->point->x));3152 helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));3153 double psi = BaseLineVector.Angle(&helper);3154 if (OrthogonalVector.ScalarProduct(&helper) > 0) {3155 psi = 2.*M_PI - psi;3156 }3157 3158 cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;3159 cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;3160 3161 // return comparison3162 return phi < psi;3163 }3164 3165 810 /** Tesselates the non convex boundary by rolling a virtual sphere along the surface of the molecule. 3166 811 * \param *out output stream for debugging … … 3176 821 bool freeTess = false; 3177 822 bool freeLC = false; 823 ofstream *tempstream = NULL; 824 char NumberName[255]; 825 int TriangleFilesWritten = 0; 826 3178 827 *out << Verbose(1) << "Entering search for non convex hull. " << endl; 3179 828 if (Tess == NULL) { … … 3193 842 } 3194 843 3195 Tess->Find_starting_triangle(out, mol,RADIUS, LCList);844 Tess->Find_starting_triangle(out, RADIUS, LCList); 3196 845 3197 846 baseline = Tess->LinesOnBoundary.begin(); 3198 847 while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) { 3199 848 if (baseline->second->TrianglesCount == 1) { 3200 failflag = Tess->Find_next_suitable_triangle(out, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename, LCList); //the line is there, so there is a triangle, but only one.849 failflag = Tess->Find_next_suitable_triangle(out, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, LCList); //the line is there, so there is a triangle, but only one. 3201 850 flag = flag || failflag; 3202 851 if (!failflag) … … 3214 863 flag = false; 3215 864 } 3216 } 865 866 // write temporary envelope 867 if ((DoSingleStepOutput && (Tess->TrianglesOnBoundaryCount % 1 == 0))) { // if we have a new triangle and want to output each new triangle configuration 868 class BoundaryTriangleSet *triangle = (Tess->TrianglesOnBoundary.end()--)->second; 869 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, triangle->endpoints[0]->node->Name, triangle->endpoints[1]->node->Name, triangle->endpoints[2]->node->Name); 870 if (DoTecplotOutput) { 871 string NameofTempFile(filename); 872 NameofTempFile.append(NumberName); 873 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 874 NameofTempFile.erase(npos, 1); 875 NameofTempFile.append(TecplotSuffix); 876 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 877 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 878 write_tecplot_file(out, tempstream, Tess, mol, TriangleFilesWritten); 879 tempstream->close(); 880 tempstream->flush(); 881 delete(tempstream); 882 } 883 884 if (DoRaster3DOutput) { 885 string NameofTempFile(filename); 886 NameofTempFile.append(NumberName); 887 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 888 NameofTempFile.erase(npos, 1); 889 NameofTempFile.append(Raster3DSuffix); 890 cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 891 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 892 write_raster3d_file(out, tempstream, Tess, mol); 893 // // include the current position of the virtual sphere in the temporary raster3d file 894 // // make the circumsphere's center absolute again 895 // helper.CopyVector(BaseRay->endpoints[0]->node->node); 896 // helper.AddVector(BaseRay->endpoints[1]->node->node); 897 // helper.Scale(0.5); 898 // (*it)->OptCenter.AddVector(&helper); 899 // Vector *center = mol->DetermineCenterOfAll(out); 900 // (*it)->OptCenter.SubtractVector(center); 901 // delete(center); 902 // // and add to file plus translucency object 903 // *tempstream << "# current virtual sphere\n"; 904 // *tempstream << "8\n 25.0 0.6 -1.0 -1.0 -1.0 0.2 0 0 0 0\n"; 905 // *tempstream << "2\n " << (*it)->OptCenter.x[0] << " " 906 // << (*it)->OptCenter.x[1] << " " << (*it)->OptCenter.x[2] 907 // << "\t" << RADIUS << "\t1 0 0\n"; 908 // *tempstream << "9\n terminating special property\n"; 909 tempstream->close(); 910 tempstream->flush(); 911 delete(tempstream); 912 } 913 if (DoTecplotOutput || DoRaster3DOutput) 914 TriangleFilesWritten++; 915 } 916 } 917 918 // write final envelope 3217 919 if (filename != 0) { 3218 920 *out << Verbose(1) << "Writing final tecplot file\n"; -
src/boundary.hpp
r2319ed r357fba 1 1 #ifndef BOUNDARY_HPP_ 2 2 #define BOUNDARY_HPP_ 3 4 class BoundaryPointSet;5 class BoundaryLineSet;6 class BoundaryTriangleSet;7 class CandidateForTesselation;8 3 9 4 // include config.h … … 17 12 #include <deque> 18 13 19 #include <gsl/gsl_poly.h>20 21 14 #include "linkedcell.hpp" 22 15 #include "molecules.hpp" 16 #include "tesselation.hpp" 17 #include "tesselationhelpers.hpp" 23 18 24 template <typename T> void SetEndpointsOrdered(T endpoints[2], T endpoint1, T endpoint2) 25 { 26 if (endpoint1->Nr < endpoint2->Nr) { 27 endpoints[0] = endpoint1; 28 endpoints[1] = endpoint2; 29 } else { 30 endpoints[0] = endpoint2; 31 endpoints[1] = endpoint1; 32 } 33 }; 34 35 class BoundaryPointSet { 36 public: 37 BoundaryPointSet(); 38 BoundaryPointSet(atom *Walker); 39 ~BoundaryPointSet(); 40 41 void AddLine(class BoundaryLineSet *line); 42 43 LineMap lines; 44 int LinesCount; 45 atom *node; 46 int Nr; 47 }; 48 49 class BoundaryLineSet { 50 public: 51 BoundaryLineSet(); 52 BoundaryLineSet(class BoundaryPointSet *Point[2], int number); 53 ~BoundaryLineSet(); 54 55 void AddTriangle(class BoundaryTriangleSet *triangle); 56 bool IsConnectedTo(class BoundaryLineSet *line); 57 bool ContainsBoundaryPoint(class BoundaryPointSet *point); 58 bool CheckConvexityCriterion(ofstream *out); 59 60 class BoundaryPointSet *endpoints[2]; 61 TriangleMap triangles; 62 int TrianglesCount; 63 int Nr; 64 }; 65 66 class BoundaryTriangleSet { 67 public: 68 BoundaryTriangleSet(); 69 BoundaryTriangleSet(class BoundaryLineSet *line[3], int number); 70 ~BoundaryTriangleSet(); 71 72 void GetNormalVector(Vector &NormalVector); 73 bool GetIntersectionInsideTriangle(ofstream *out, Vector *MolCenter, Vector *x, Vector *Intersection); 74 bool ContainsBoundaryLine(class BoundaryLineSet *line); 75 bool ContainsBoundaryPoint(class BoundaryPointSet *point); 76 77 class BoundaryPointSet *endpoints[3]; 78 class BoundaryLineSet *lines[3]; 79 Vector NormalVector; 80 int Nr; 81 }; 82 83 84 class CandidateForTesselation { 85 public : 86 CandidateForTesselation(atom* candidate, BoundaryLineSet* currentBaseLine, Vector OptCandidateCenter, Vector OtherOptCandidateCenter); 87 ~CandidateForTesselation(); 88 atom *point; 89 BoundaryLineSet *BaseLine; 90 Vector OptCenter; 91 Vector OtherOptCenter; 92 }; 93 94 95 class Tesselation { 96 public: 97 98 Tesselation(); 99 ~Tesselation(); 100 101 void TesselateOnBoundary(ofstream *out, molecule *mol); 102 void GuessStartingTriangle(ofstream *out); 103 void AddPoint(atom * Walker); 104 void AddTrianglePoint(atom* Candidate, int n); 105 void AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n); 106 void AlwaysAddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n); 107 void AddTriangle(); 108 void Find_starting_triangle(ofstream *out, molecule* mol, const double RADIUS, LinkedCell *LC); 109 bool Find_next_suitable_triangle(ofstream *out, molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, const char *filename, LinkedCell *LC); 110 int CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]); 111 void Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent, int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol); 112 class BoundaryTriangleSet * FindClosestTriangleToPoint(ofstream *out, Vector *x); 113 bool IsInside(Vector *pointer); 114 bool InsertStraddlingPoints(ofstream *out, molecule *mol); 115 bool CorrectConcaveBaselines(ofstream *out); 116 117 PointMap PointsOnBoundary; 118 LineMap LinesOnBoundary; 119 TriangleMap TrianglesOnBoundary; 120 class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions 121 class BoundaryPointSet *BPS[2]; 122 class BoundaryLineSet *BLS[3]; 123 class BoundaryTriangleSet *BTS; 124 int PointsOnBoundaryCount; 125 int LinesOnBoundaryCount; 126 int TrianglesOnBoundaryCount; 127 int TriangleFilesWritten; 128 }; 129 130 131 ostream & operator << (ostream &ost, BoundaryPointSet &a); 132 ostream & operator << (ostream &ost, BoundaryLineSet &a); 133 ostream & operator << (ostream &ost, BoundaryTriangleSet &a); 134 19 #define DEBUG 1 20 #define DoSingleStepOutput 0 21 #define DoTecplotOutput 1 22 #define DoRaster3DOutput 1 23 #define DoVRMLOutput 1 24 #define TecplotSuffix ".dat" 25 #define Raster3DSuffix ".r3d" 26 #define VRMLSUffix ".wrl" 135 27 136 28 double VolumeOfConvexEnvelope(ofstream *out, class Tesselation *TesselStruct, class config *configuration); … … 141 33 void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *T, class LinkedCell *LC, const char *tempbasename, const double RADIUS); 142 34 void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC); 143 bool Choose_preferable_third_point(atom *Candidate, atom *OptCandidate, class BoundaryLineSet *BaseLine, atom *ThirdNode, Tesselation *Tess); 144 bool existsIntersection(Vector point1, Vector point2, Vector point3, Vector point4); 145 bool sortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2); 35 Boundaries *GetBoundaryPoints(ofstream *out, molecule *mol); 146 36 147 37 #endif /*BOUNDARY_HPP_*/ -
src/builder.cpp
r2319ed r357fba 1229 1229 } 1230 1230 molecules->SimpleMultiAdd(mol, src, N); 1231 delete[](src); 1231 delete(src); 1232 1232 1233 // ... and translate back 1233 1234 for (MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) { -
src/config.cpp
r2319ed r357fba 276 276 277 277 /** Readin of Thermostat related values from parameter file. 278 * \param * source parameterfile279 */ 280 void config::InitThermostats( ifstream *source)278 * \param *fb file buffer containing the config file 279 */ 280 void config::InitThermostats(class ConfigFileBuffer *fb) 281 281 { 282 282 char *thermo = MallocString(12, "IonsInitRead: thermo"); … … 284 284 285 285 // read desired Thermostat from file along with needed additional parameters 286 if (ParseForParameter(verbose, source,"Thermostat", 0, 1, 1, string_type, thermo, 1, optional)) {286 if (ParseForParameter(verbose,fb,"Thermostat", 0, 1, 1, string_type, thermo, 1, optional)) { 287 287 if (strcmp(thermo, ThermostatNames[0]) == 0) { // None 288 288 if (ThermostatImplemented[0] == 1) { … … 295 295 if (ThermostatImplemented[1] == 1) { 296 296 Thermostat = Woodcock; 297 ParseForParameter(verbose, source,"Thermostat", 0, 2, 1, int_type, &ScaleTempStep, 1, critical); // read scaling frequency297 ParseForParameter(verbose,fb,"Thermostat", 0, 2, 1, int_type, &ScaleTempStep, 1, critical); // read scaling frequency 298 298 } else { 299 299 cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl; … … 303 303 if (ThermostatImplemented[2] == 1) { 304 304 Thermostat = Gaussian; 305 ParseForParameter(verbose, source,"Thermostat", 0, 2, 1, int_type, &ScaleTempStep, 1, critical); // read collision rate305 ParseForParameter(verbose,fb,"Thermostat", 0, 2, 1, int_type, &ScaleTempStep, 1, critical); // read collision rate 306 306 } else { 307 307 cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl; … … 311 311 if (ThermostatImplemented[3] == 1) { 312 312 Thermostat = Langevin; 313 ParseForParameter(verbose, source,"Thermostat", 0, 2, 1, double_type, &TempFrequency, 1, critical); // read gamma314 if (ParseForParameter(verbose, source,"Thermostat", 0, 3, 1, double_type, &alpha, 1, optional)) {313 ParseForParameter(verbose,fb,"Thermostat", 0, 2, 1, double_type, &TempFrequency, 1, critical); // read gamma 314 if (ParseForParameter(verbose,fb,"Thermostat", 0, 3, 1, double_type, &alpha, 1, optional)) { 315 315 cout << Verbose(2) << "Extended Stochastic Thermostat detected with interpolation coefficient " << alpha << "." << endl; 316 316 } else { … … 324 324 if (ThermostatImplemented[4] == 1) { 325 325 Thermostat = Berendsen; 326 ParseForParameter(verbose, source,"Thermostat", 0, 2, 1, double_type, &TempFrequency, 1, critical); // read \tau_T326 ParseForParameter(verbose,fb,"Thermostat", 0, 2, 1, double_type, &TempFrequency, 1, critical); // read \tau_T 327 327 } else { 328 328 cout << Verbose(1) << "Warning: " << ThermostatNames[0] << " thermostat not implemented, falling back to None." << endl; … … 332 332 if (ThermostatImplemented[5] == 1) { 333 333 Thermostat = NoseHoover; 334 ParseForParameter(verbose, source,"Thermostat", 0, 2, 1, double_type, &HooverMass, 1, critical); // read Hoovermass334 ParseForParameter(verbose,fb,"Thermostat", 0, 2, 1, double_type, &HooverMass, 1, critical); // read Hoovermass 335 335 alpha = 0.; 336 336 } else { … … 704 704 return; 705 705 } 706 file->close(); 707 delete(file); 706 708 RetrieveConfigPathAndName(filename); 707 709 … … 722 724 double value[3]; 723 725 724 InitThermostats( file);726 InitThermostats(FileBuffer); 725 727 726 728 /* Namen einlesen */ -
src/ellipsoid.cpp
r2319ed r357fba 6 6 */ 7 7 8 #include <gsl/gsl_multimin.h> 9 #include <gsl/gsl_vector.h> 10 11 #include "boundary.hpp" 8 12 #include "ellipsoid.hpp" 9 13 … … 221 225 set<int>::iterator current; 222 226 int index; 223 atom*Candidate = NULL;224 Linked Atoms *List = NULL;227 TesselPoint *Candidate = NULL; 228 LinkedNodes *List = NULL; 225 229 *out << Verbose(2) << "Begin of PickRandomPointSet" << endl; 226 230 … … 288 292 // else 289 293 // *out << Verbose(2) << "Cell is empty ... " << endl; 290 for (Linked Atoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {294 for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 291 295 if ((current != PickedAtomNrs.end()) && (*current == index)) { 292 296 Candidate = (*Runner); 293 297 *out << Verbose(2) << "Current picked node is " << **Runner << " with index " << index << "." << endl; 294 x[PointsPicked++].CopyVector( &(Candidate->x)); // we have one more atom picked298 x[PointsPicked++].CopyVector(Candidate->node); // we have one more atom picked 295 299 current++; // next pre-picked atom 296 300 } … … 338 342 //*out << Verbose(3) << "Current node is " << *Runner->second->node << " with " << value << " ... " << threshold << ": "; 339 343 if (value > threshold) { 340 x[PointsPicked].CopyVector( &(Runner->second->node->x));344 x[PointsPicked].CopyVector(Runner->second->node->node); 341 345 PointsPicked++; 342 346 //*out << "IN." << endl; … … 375 379 Center.Zero(); 376 380 for (PointMap::iterator Runner = T->PointsOnBoundary.begin(); Runner != T->PointsOnBoundary.end(); Runner++) 377 Center.AddVector( &Runner->second->node->x);381 Center.AddVector(Runner->second->node->node); 378 382 Center.Scale(1./T->PointsOnBoundaryCount); 379 383 *out << Verbose(1) << "Center is at " << Center << "." << endl; -
src/ellipsoid.hpp
r2319ed r357fba 14 14 #endif 15 15 16 #include <cstdlib> 17 18 #include "boundary.hpp" 16 #include "linkedcell.hpp" 19 17 #include "vector.hpp" 20 18 -
src/linkedcell.cpp
r2319ed r357fba 1 1 #include "linkedcell.hpp" 2 2 #include "molecules.hpp" 3 #include "tesselation.hpp" 4 5 // ========================================================= class LinkedCell =========================================== 6 3 7 4 8 /** Constructor for class LinkedCell. … … 16 20 17 21 /** Puts all atoms in \a *mol into a linked cell list with cell's lengths of \a RADIUS 18 * \param * mol molecule structure with all Atom's22 * \param *set LCNodeSet class with all LCNode's 19 23 * \param RADIUS edge length of cells 20 24 */ 21 LinkedCell::LinkedCell( molecule *mol, double radius)25 LinkedCell::LinkedCell(PointCloud *set, double radius) 22 26 { 23 atom*Walker = NULL;27 TesselPoint *Walker = NULL; 24 28 25 29 RADIUS = radius; … … 31 35 min.Zero(); 32 36 cout << Verbose(1) << "Begin of LinkedCell" << endl; 33 if ( mol->start->next == mol->end) {34 cerr << "ERROR: molecule contains no atoms!" << endl;37 if (set->IsEmpty()) { 38 cerr << "ERROR: set contains no linked cell nodes!" << endl; 35 39 return; 36 40 } 37 41 // 1. find max and min per axis of atoms 38 Walker = mol->start->next; 42 set->GoToFirst(); 43 Walker = set->GetPoint(); 39 44 for (int i=0;i<NDIM;i++) { 40 max.x[i] = Walker-> x.x[i];41 min.x[i] = Walker-> x.x[i];45 max.x[i] = Walker->node->x[i]; 46 min.x[i] = Walker->node->x[i]; 42 47 } 43 while (Walker != mol->end) { 48 set->GoToFirst(); 49 while (!set->IsLast()) { 50 Walker = set->GetPoint(); 44 51 for (int i=0;i<NDIM;i++) { 45 if (max.x[i] < Walker-> x.x[i])46 max.x[i] = Walker-> x.x[i];47 if (min.x[i] > Walker-> x.x[i])48 min.x[i] = Walker-> x.x[i];52 if (max.x[i] < Walker->node->x[i]) 53 max.x[i] = Walker->node->x[i]; 54 if (min.x[i] > Walker->node->x[i]) 55 min.x[i] = Walker->node->x[i]; 49 56 } 50 Walker = Walker->next;57 set->GoToNext(); 51 58 } 52 59 cout << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl; 53 60 54 // 2. find then umber of cells per axis61 // 2. find then number of cells per axis 55 62 for (int i=0;i<NDIM;i++) { 56 63 N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1; … … 64 71 return; 65 72 } 66 LC = new Linked Atoms[N[0]*N[1]*N[2]];73 LC = new LinkedNodes[N[0]*N[1]*N[2]]; 67 74 for (index=0;index<N[0]*N[1]*N[2];index++) { 68 75 LC [index].clear(); … … 72 79 // 4. put each atom into its respective cell 73 80 cout << Verbose(2) << "Filling cells ... "; 74 Walker = mol->start;75 while ( Walker->next != mol->end) {76 Walker = Walker->next;81 set->GoToFirst(); 82 while (!set->IsLast()) { 83 Walker = set->GetPoint(); 77 84 for (int i=0;i<NDIM;i++) { 78 n[i] = (int)floor((Walker-> x.x[i] - min.x[i])/RADIUS);85 n[i] = (int)floor((Walker->node->x[i] - min.x[i])/RADIUS); 79 86 } 80 87 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 81 88 LC[index].push_back(Walker); 82 89 //cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl; 90 set->GoToNext(); 83 91 } 84 92 cout << "done." << endl; … … 118 126 * \return LinkedAtoms pointer to current cell, NULL if LinkedCell::n[] are out of bounds. 119 127 */ 120 Linked Atoms* LinkedCell::GetCurrentCell()128 LinkedNodes* LinkedCell::GetCurrentCell() 121 129 { 122 130 if (CheckBounds()) { … … 128 136 }; 129 137 130 /** Calculates the index for a given atom*Walker.131 * \param *Walker atom to set index to138 /** Calculates the index for a given LCNode *Walker. 139 * \param *Walker LCNode to set index tos 132 140 * \return if the atom is also found in this cell - true, else - false 133 141 */ 134 bool LinkedCell::SetIndexTo Atom(atom*Walker)142 bool LinkedCell::SetIndexToNode(TesselPoint *Walker) 135 143 { 136 144 bool status = false; 137 145 for (int i=0;i<NDIM;i++) { 138 n[i] = (int)floor((Walker-> x.x[i] - min.x[i])/RADIUS);146 n[i] = (int)floor((Walker->node->x[i] - min.x[i])/RADIUS); 139 147 } 140 148 index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2]; 141 149 if (CheckBounds()) { 142 for (Linked Atoms::iterator Runner = LC[index].begin(); Runner != LC[index].end(); Runner++)150 for (LinkedNodes::iterator Runner = LC[index].begin(); Runner != LC[index].end(); Runner++) 143 151 status = status || ((*Runner) == Walker); 144 152 return status; 145 153 } else { 146 cerr << Verbose(1) << "ERROR: Atom "<< *Walker << " at " << Walker->x<< " is out of bounds." << endl;154 cerr << Verbose(1) << "ERROR: Node at " << *Walker << " is out of bounds." << endl; 147 155 return false; 148 156 } -
src/linkedcell.hpp
r2319ed r357fba 1 /* 2 * linkedcell.hpp 3 * 4 * If the linked cell should be usable, the class has to inherit LCNodeSet and the nodes (containing the Vectors) have to inherit LCNode. This works well 5 * for molecule and atom classes. 6 * 7 * Created on: Aug 3, 2009 8 * Author: heber 9 */ 10 1 11 #ifndef LINKEDCELL_HPP_ 2 12 #define LINKEDCELL_HPP_ 13 14 using namespace std; 3 15 4 16 // include config.h … … 7 19 #endif 8 20 9 #include "molecules.hpp"21 #include <list> 10 22 11 #define LinkedAtoms list <atom *> 23 #include "defs.hpp" 24 #include "helpers.hpp" 25 #include "vector.hpp" 12 26 13 class LinkedCell{ 27 class TesselPoint; 28 class PointCloud; 29 30 #define LinkedNodes list<TesselPoint *> 31 32 /** Linked Cell class for containing Vectors in real space efficiently. 33 */ 34 class LinkedCell { 14 35 public: 15 36 Vector max; // upper boundary 16 37 Vector min; // lower boundary 17 Linked Atoms *LC; // linked cell list38 LinkedNodes *LC; // linked cell list 18 39 double RADIUS; // cell edge length 19 40 int N[NDIM]; // number of cells per axis … … 22 43 23 44 LinkedCell(); 24 LinkedCell( molecule *mol, double RADIUS);45 LinkedCell(PointCloud *set, double RADIUS); 25 46 ~LinkedCell(); 26 Linked Atoms* GetCurrentCell();27 bool SetIndexTo Atom(atom*Walker);47 LinkedNodes* GetCurrentCell(); 48 bool SetIndexToNode(TesselPoint *Walker); 28 49 bool SetIndexToVector(Vector *x); 29 50 bool CheckBounds(); 30 51 31 52 // not implemented yet 32 bool Add Atom(atom*Walker);33 bool Delete Atom(atom*Walker);34 bool Move Atom(atom*Walker);53 bool AddNode(Vector *Walker); 54 bool DeleteNode(Vector *Walker); 55 bool MoveNode(Vector *Walker); 35 56 }; 36 57 -
src/molecules.cpp
r2319ed r357fba 42 42 end->father = NULL; 43 43 link(start,end); 44 InternalPointer = start; 44 45 // init bond chain list 45 46 first = new bond(start, end, 1, -1); … … 82 83 delete(end); 83 84 delete(start); 85 }; 86 87 88 /** Determine center of all atoms. 89 * \param *out output stream for debugging 90 * \return pointer to allocated with central coordinates 91 */ 92 Vector *molecule::GetCenter(ofstream *out) 93 { 94 Vector *center = DetermineCenterOfAll(out); 95 return center; 96 }; 97 98 /** Return current atom in the list. 99 * \return pointer to atom or NULL if none present 100 */ 101 TesselPoint *molecule::GetPoint() 102 { 103 if ((InternalPointer != start) && (InternalPointer != end)) 104 return InternalPointer; 105 else 106 return NULL; 107 }; 108 109 /** Return pointer to one after last atom in the list. 110 * \return pointer to end marker 111 */ 112 TesselPoint *molecule::GetTerminalPoint() 113 { 114 return end; 115 }; 116 117 /** Go to next atom. 118 * Stops at last one. 119 */ 120 void molecule::GoToNext() 121 { 122 if (InternalPointer->next != end) 123 InternalPointer = InternalPointer->next; 124 }; 125 126 /** Go to previous atom. 127 * Stops at first one. 128 */ 129 void molecule::GoToPrevious() 130 { 131 if (InternalPointer->previous != start) 132 InternalPointer = InternalPointer->previous; 133 }; 134 135 /** Goes to first atom. 136 */ 137 void molecule::GoToFirst() 138 { 139 InternalPointer = start->next; 140 }; 141 142 /** Goes to last atom. 143 */ 144 void molecule::GoToLast() 145 { 146 InternalPointer = end->previous; 147 }; 148 149 /** Checks whether we have any atoms in molecule. 150 * \return true - no atoms, false - not empty 151 */ 152 bool molecule::IsEmpty() 153 { 154 return (start->next == end); 155 }; 156 157 /** Checks whether we are at the last atom 158 * \return true - current atom is last one, false - is not last one 159 */ 160 bool molecule::IsLast() 161 { 162 return (InternalPointer->next == end); 84 163 }; 85 164 -
src/molecules.hpp
r2319ed r357fba 25 25 #include <vector> 26 26 27 #include "atom.hpp" 28 #include "bond.hpp" 27 29 #include "helpers.hpp" 30 #include "linkedcell.hpp" 28 31 #include "parser.hpp" 29 32 #include "periodentafel.hpp" 30 33 #include "stackclass.hpp" 34 #include "tesselation.hpp" 31 35 #include "vector.hpp" 32 36 33 class atom;34 class bond;35 37 class config; 36 38 class molecule; … … 38 40 class MoleculeListClass; 39 41 class Verbose; 40 class Tesselation;41 42 42 43 /******************************** Some definitions for easier reading **********************************/ … … 58 59 #define BoundariesTestPair pair< Boundaries::iterator, bool> 59 60 60 #define PointMap map < int, class BoundaryPointSet * >61 #define PointPair pair < int, class BoundaryPointSet * >62 #define PointTestPair pair < PointMap::iterator, bool >63 #define CandidateList list <class CandidateForTesselation *>64 65 #define LineMap multimap < int, class BoundaryLineSet * >66 #define LinePair pair < int, class BoundaryLineSet * >67 #define LineTestPair pair < LineMap::iterator, bool >68 69 #define TriangleMap map < int, class BoundaryTriangleSet * >70 #define TrianglePair pair < int, class BoundaryTriangleSet * >71 #define TriangleTestPair pair < TrianglePair::iterator, bool >72 73 #define DistanceMultiMap multimap <double, pair < PointMap::iterator, PointMap::iterator> >74 #define DistanceMultiMapPair pair <double, pair < PointMap::iterator, PointMap::iterator> >75 76 61 #define MoleculeList list <molecule *> 77 62 #define MoleculeListTest pair <MoleculeList::iterator, bool> … … 125 110 }; 126 111 127 /** Single atom.128 * Class incoporates position, type129 */130 class atom {131 public:132 Vector x; //!< coordinate array of atom, giving position within cell133 Vector v; //!< velocity array of atom134 element *type; //!< pointing to element135 atom *previous; //!< previous atom in molecule list136 atom *next; //!< next atom in molecule list137 atom *father; //!< In many-body bond order fragmentations points to originating atom138 atom *Ancestor; //!< "Father" in Depth-First-Search139 char *Name; //!< unique name used during many-body bond-order fragmentation140 int FixedIon; //!< config variable that states whether forces act on the ion or not141 int *sort; //!< sort criteria142 int nr; //!< continuous, unique number143 int GraphNr; //!< unique number, given in DepthFirstSearchAnalysis()144 int *ComponentNr;//!< belongs to this nonseparable components, given in DepthFirstSearchAnalysis() (if more than one, then is SeparationVertex)145 int LowpointNr; //!< needed in DepthFirstSearchAnalysis() to detect nonseparable components, is the lowest possible number of an atom to reach via tree edges only followed by at most one back edge.146 bool SeparationVertex; //!< whether this atom separates off subsets of atoms or not, determined in DepthFirstSearchAnalysis()147 bool IsCyclic; //!< whether atom belong to as cycle or not, determined in DepthFirstSearchAnalysis()148 unsigned char AdaptiveOrder; //!< current present bond order at site (0 means "not set")149 bool MaxOrder; //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not150 151 atom();152 atom(class atom *pointer);153 ~atom();154 155 bool Output(int ElementNo, int AtomNo, ofstream *out, const char *comment = NULL) const;156 bool OutputXYZLine(ofstream *out) const;157 atom *GetTrueFather();158 bool Compare(atom &ptr);159 160 private:161 };162 163 ostream & operator << (ostream &ost, const atom &a);164 165 /** Bonds between atoms.166 * Class incorporates bonds between atoms in a molecule,167 * used to derive tge fragments in many-body bond order168 * calculations.169 */170 class bond {171 public:172 atom *leftatom; //!< first bond partner173 atom *rightatom; //!< second bond partner174 bond *previous; //!< previous atom in molecule list175 bond *next; //!< next atom in molecule list176 int HydrogenBond; //!< Number of hydrogen atoms in the bond177 int BondDegree; //!< single, double, triple, ... bond178 int nr; //!< unique number in a molecule, updated by molecule::CreateAdjacencyList()179 bool Cyclic; //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis()180 enum EdgeType Type;//!< whether this is a tree or back edge181 182 atom * GetOtherAtom(atom *Atom) const;183 bond * GetFirstBond();184 bond * GetLastBond();185 186 bool MarkUsed(enum Shading color);187 enum Shading IsUsed();188 void ResetUsed();189 bool Contains(const atom *ptr);190 bool Contains(const int nr);191 192 bond();193 bond(atom *left, atom *right);194 bond(atom *left, atom *right, int degree);195 bond(atom *left, atom *right, int degree, int number);196 ~bond();197 198 private:199 enum Shading Used; //!< marker in depth-first search, DepthFirstSearchAnalysis()200 };201 202 203 ostream & operator << (ostream &ost, const bond &b);204 112 205 113 #define MaxThermostats 6 //!< maximum number of thermostat entries in Ions#ThermostatNames and Ions#ThermostatImplemented … … 210 118 * Class incorporates number of types 211 119 */ 212 class molecule {120 class molecule : public PointCloud { 213 121 public: 214 122 double cell_size[6];//!< cell size … … 234 142 char name[MAXSTRINGSIZE]; //!< arbitrary name 235 143 int IndexNr; //!< index of molecule in a MoleculeListClass 144 class Tesselation *TesselStruct; 236 145 237 146 molecule(periodentafel *teil); 238 147 ~molecule(); 148 149 // re-definition of virtual functions from PointCloud 150 Vector *GetCenter(ofstream *out); 151 TesselPoint *GetPoint(); 152 TesselPoint *GetTerminalPoint(); 153 void GoToNext(); 154 void GoToPrevious(); 155 void GoToFirst(); 156 void GoToLast(); 157 bool IsEmpty(); 158 bool IsLast(); 239 159 240 160 /// remove atoms from molecule. … … 350 270 private: 351 271 int last_atom; //!< number given to last atom 272 atom *InternalPointer; //!< internal pointer for PointCloud 352 273 }; 353 274 … … 524 445 char *GetDefaultPath() const; 525 446 void SetDefaultPath(const char *path); 526 void InitThermostats( ifstream *source);447 void InitThermostats(class ConfigFileBuffer *fb); 527 448 }; 528 449 -
src/vector.hpp
r2319ed r357fba 1 1 #ifndef VECTOR_HPP_ 2 2 #define VECTOR_HPP_ 3 4 using namespace std; 5 6 #include "helpers.hpp" 3 7 4 8 class Vector;
Note:
See TracChangeset
for help on using the changeset viewer.