Changeset e0c5b1 for molecuilder/src/boundary.cpp
- Timestamp:
- Dec 3, 2008, 2:12:05 PM (17 years ago)
- Children:
- 3e20fe
- Parents:
- f5b58e
- File:
-
- 1 edited
-
molecuilder/src/boundary.cpp (modified) (62 diffs)
Legend:
- Unmodified
- Added
- Removed
-
molecuilder/src/boundary.cpp
rf5b58e re0c5b1 3 3 4 4 5 // =================spaeter gebrauchte6 void Find_next_suitable_point(atom a, atom b, atom Candidate, int n, Vector *d1, Vector *d2, double *Storage, const double RADIUS, molecule mol);7 void Find_non_convex_border(Tesselation Tess, molecule mol);8 5 9 6 … … 29 26 }; 30 27 31 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 28 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 32 29 { 33 30 cout << Verbose(6) << "Adding line " << *line << " to " << *this << "." << endl; … … 40 37 }; 41 38 42 ostream & operator << (ostream &ost, BoundaryPointSet &a) 39 ostream & operator << (ostream &ost, BoundaryPointSet &a) 43 40 { 44 41 ost << "[" << a.Nr << "|" << a.node->Name << "]"; … … 73 70 { 74 71 for (int i=0;i<2;i++) { 75 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 72 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 76 73 endpoints[i]->lines.erase(Nr); 77 74 LineMap::iterator tester = endpoints[i]->lines.begin(); … … 85 82 }; 86 83 87 void BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 84 void BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 88 85 { 89 86 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." << endl; … … 92 89 }; 93 90 94 ostream & operator << (ostream &ost, BoundaryLineSet &a) 91 ostream & operator << (ostream &ost, BoundaryLineSet &a) 95 92 { 96 93 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]"; … … 125 122 for (int j=0;j<2;j++) { // for both endpoints 126 123 OrderMap.insert ( pair <int, class BoundaryPointSet * >( line[i]->endpoints[j]->Nr, line[i]->endpoints[j]) ); 127 // and we don't care whether insertion fails 124 // and we don't care whether insertion fails 128 125 } 129 126 // set endpoints … … 161 158 // get normal vector 162 159 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, &endpoints[2]->node->x); 163 160 164 161 // make it always point inward (any offset vector onto plane projected onto normal vector suffices) 165 162 if (endpoints[0]->node->x.Projection(&NormalVector) > 0) … … 167 164 }; 168 165 169 ostream & operator << (ostream &ost, BoundaryTriangleSet &a) 166 ostream & operator << (ostream &ost, BoundaryTriangleSet &a) 170 167 { 171 168 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; … … 213 210 LineMap LinesOnBoundary; 214 211 TriangleMap TrianglesOnBoundary; 215 212 216 213 *out << Verbose(1) << "Finding all boundary points." << endl; 217 214 Boundaries *BoundaryPoints = new Boundaries [NDIM]; // first is alpha, second is (r, nr) … … 250 247 else 251 248 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 252 249 253 250 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 254 251 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) { … … 268 265 Walker->x.Output(out); 269 266 *out << endl; 270 double tmp = ProjectedVector.Norm(); 267 double tmp = ProjectedVector.Norm(); 271 268 if (tmp > BoundaryTestPair.first->second.first) { 272 269 BoundaryTestPair.first->second.first = tmp; 273 BoundaryTestPair.first->second.second = Walker; 270 BoundaryTestPair.first->second.second = Walker; 274 271 *out << Verbose(2) << "Keeping new vector." << endl; 275 272 } else if (tmp == BoundaryTestPair.first->second.first) { … … 319 316 } 320 317 // check distance 321 318 322 319 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 323 320 { … … 328 325 // SideA.Output(out); 329 326 // *out << endl; 330 327 331 328 SideB.CopyVector(&right->second.second->x); 332 329 SideB.ProjectOntoPlane(&AxisVector); … … 334 331 // SideB.Output(out); 335 332 // *out << endl; 336 333 337 334 SideC.CopyVector(&left->second.second->x); 338 335 SideC.SubtractVector(&right->second.second->x); … … 341 338 // SideC.Output(out); 342 339 // *out << endl; 343 340 344 341 SideH.CopyVector(&runner->second.second->x); 345 342 SideH.ProjectOntoPlane(&AxisVector); … … 347 344 // SideH.Output(out); 348 345 // *out << endl; 349 346 350 347 // calculate each length 351 348 double a = SideA.Norm(); … … 355 352 // calculate the angles 356 353 double alpha = SideA.Angle(&SideH); 357 double beta = SideA.Angle(&SideC); 354 double beta = SideA.Angle(&SideC); 358 355 double gamma = SideB.Angle(&SideH); 359 356 double delta = SideC.Angle(&SideH); 360 357 double MinDistance = a * sin(beta)/(sin(delta)) * (((alpha < M_PI/2.) || (gamma < M_PI/2.)) ? 1. : -1.); 361 // *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; 358 // *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl; 362 359 //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl; 363 360 if ((fabs(h/fabs(h) - MinDistance/fabs(MinDistance)) < MYEPSILON) && (h < MinDistance)) { … … 370 367 } 371 368 } while (flag); 372 } 369 } 373 370 return BoundaryPoints; 374 371 }; … … 381 378 * \param IsAngstroem whether we have angstroem or atomic units 382 379 * \return NDIM array of the diameters 383 */ 380 */ 384 381 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem) 385 382 { … … 393 390 *out << Verbose(1) << "Using given boundary points set." << endl; 394 391 } 395 392 396 393 // determine biggest "diameter" of cluster for each axis 397 394 Boundaries::iterator Neighbour, OtherNeighbour; … … 418 415 DistanceVector.SubtractVector(&Neighbour->second.second->x); 419 416 do { // seek for neighbour pair where it flips 420 OldComponent = DistanceVector.x[Othercomponent]; 417 OldComponent = DistanceVector.x[Othercomponent]; 421 418 Neighbour++; 422 419 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around … … 431 428 OtherNeighbour = BoundaryPoints[axis].end(); 432 429 OtherNeighbour--; 433 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 430 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 434 431 // now we have found the pair: Neighbour and OtherNeighbour 435 432 OtherVector.CopyVector(&runner->second.second->x); … … 466 463 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired 467 464 * \param *mol molecule structure representing the cluster 468 * \return determined volume of the cluster in cubed config:GetIsAngstroem() 465 * \return determined volume of the cluster in cubed config:GetIsAngstroem() 469 466 */ 470 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPtr, molecule *mol) 467 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPtr, molecule *mol) 471 468 { 472 469 bool IsAngstroem = configuration->GetIsAngstroem(); … … 477 474 double volume = 0.; 478 475 double PyramidVolume = 0.; 479 double G,h; 476 double G,h; 480 477 Vector x,y; 481 478 double a,b,c; 482 479 483 Find_non_convex_border(*TesselStruct, *mol);480 Find_non_convex_border(*TesselStruct, mol); 484 481 /* 485 482 // 1. calculate center of gravity 486 483 *out << endl; 487 484 Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out); 488 485 489 486 // 2. translate all points into CoG 490 487 *out << Verbose(1) << "Translating system to Center of Gravity." << endl; … … 494 491 Walker->x.Translate(CenterOfGravity); 495 492 } 496 493 497 494 // 3. Find all points on the boundary 498 495 if (BoundaryPoints == NULL) { … … 502 499 *out << Verbose(1) << "Using given boundary points set." << endl; 503 500 } 504 501 505 502 // 4. fill the boundary point list 506 503 for (int axis=0;axis<NDIM;axis++) … … 518 515 // } 519 516 // *out << endl; 520 517 521 518 // 5a. guess starting triangle 522 519 TesselStruct->GuessStartingTriangle(out); 523 520 524 521 // 5b. go through all lines, that are not yet part of two triangles (only of one so far) 525 522 TesselStruct->TesselateOnBoundary(out, configuration, mol); … … 545 542 PyramidVolume = (1./3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 546 543 *out << Verbose(2) << "Area of triangle is " << G << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " << h << " and the volume is " << PyramidVolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 547 volume += PyramidVolume; 544 volume += PyramidVolume; 548 545 } 549 546 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; … … 572 569 for (int i=0;i<mol->AtomCount;i++) 573 570 LookupList[i] = -1; 574 571 575 572 // print atom coordinates 576 573 *out << Verbose(2) << "The following triangles were created:"; … … 586 583 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) { 587 584 *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name; 588 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl; 585 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl; 589 586 } 590 587 delete[](LookupList); … … 595 592 if (BoundaryFreeFlag) 596 593 delete[](BoundaryPoints); 597 594 598 595 return volume; 599 596 }; … … 612 609 // transform to PAS 613 610 mol->PrincipalAxisSystem(out, true); 614 611 615 612 // some preparations beforehand 616 613 bool IsAngstroem = configuration->GetIsAngstroem(); … … 619 616 if (ClusterVolume == 0) 620 617 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration, BoundaryPoints, mol); 621 else 618 else 622 619 clustervolume = ClusterVolume; 623 620 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, IsAngstroem); … … 636 633 } 637 634 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) << totalmass << " atomicmassunit." << endl; 638 635 639 636 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) << totalmass/clustervolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 640 637 641 638 // solve cubic polynomial 642 639 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." << endl; … … 647 644 cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_a0 - (totalmass/clustervolume))/(celldensity-1); 648 645 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 649 646 650 647 double minimumvolume = TotalNoClusters*(GreatestDiameter[0]*GreatestDiameter[1]*GreatestDiameter[2]); 651 648 *out << Verbose(1) << "Minimum volume of the convex envelope contained in a rectangular box is " << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; … … 658 655 } else { 659 656 BoxLengths.x[0] = (repetition[0]*GreatestDiameter[0] + repetition[1]*GreatestDiameter[1] + repetition[2]*GreatestDiameter[2]); 660 BoxLengths.x[1] = (repetition[0]*repetition[1]*GreatestDiameter[0]*GreatestDiameter[1] 661 + repetition[0]*repetition[2]*GreatestDiameter[0]*GreatestDiameter[2] 657 BoxLengths.x[1] = (repetition[0]*repetition[1]*GreatestDiameter[0]*GreatestDiameter[1] 658 + repetition[0]*repetition[2]*GreatestDiameter[0]*GreatestDiameter[2] 662 659 + repetition[1]*repetition[2]*GreatestDiameter[1]*GreatestDiameter[2]); 663 660 BoxLengths.x[2] = minimumvolume - cellvolume; … … 669 666 x0 = x2; // sorted in ascending order 670 667 } 671 668 672 669 cellvolume = 1; 673 670 for(int i=0;i<NDIM;i++) { … … 675 672 cellvolume *= BoxLengths.x[i]; 676 673 } 677 674 678 675 // set new box dimensions 679 676 *out << Verbose(0) << "Translating to box with these boundaries." << endl; … … 692 689 Tesselation::Tesselation() 693 690 { 694 PointsOnBoundaryCount = 0; 695 LinesOnBoundaryCount = 0; 691 PointsOnBoundaryCount = 0; 692 LinesOnBoundaryCount = 0; 696 693 TrianglesOnBoundaryCount = 0; 697 694 }; … … 711 708 * \param *out output stream for debugging 712 709 * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster 713 */ 710 */ 714 711 void Tesselation::GuessStartingTriangle(ofstream *out) 715 712 { … … 722 719 A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily 723 720 724 // with A chosen, take each pair B,C and sort 721 // with A chosen, take each pair B,C and sort 725 722 if (A != PointsOnBoundary.end()) { 726 723 B = A; … … 746 743 // } 747 744 // *out << endl; 748 745 749 746 // 4b2. pick three baselines forming a triangle 750 747 // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate … … 758 755 PlaneVector.Output(out); 759 756 *out << endl; 760 // 4. loop over all points 757 // 4. loop over all points 761 758 double sign = 0.; 762 759 PointMap::iterator checker = PointsOnBoundary.begin(); … … 785 782 tmp = checker->second->node->x.Distance(&A->second->node->x); 786 783 int innerpoint = 0; 787 if ((tmp < A->second->node->x.Distance(&baseline->second.first->second->node->x)) 784 if ((tmp < A->second->node->x.Distance(&baseline->second.first->second->node->x)) 788 785 && (tmp < A->second->node->x.Distance(&baseline->second.second->second->node->x))) 789 786 innerpoint++; 790 787 tmp = checker->second->node->x.Distance(&baseline->second.first->second->node->x); 791 if ((tmp < baseline->second.first->second->node->x.Distance(&A->second->node->x)) 788 if ((tmp < baseline->second.first->second->node->x.Distance(&A->second->node->x)) 792 789 && (tmp < baseline->second.first->second->node->x.Distance(&baseline->second.second->second->node->x))) 793 790 innerpoint++; 794 791 tmp = checker->second->node->x.Distance(&baseline->second.second->second->node->x); 795 if ((tmp < baseline->second.second->second->node->x.Distance(&baseline->second.first->second->node->x)) 792 if ((tmp < baseline->second.second->second->node->x.Distance(&baseline->second.first->second->node->x)) 796 793 && (tmp < baseline->second.second->second->node->x.Distance(&A->second->node->x))) 797 794 innerpoint++; … … 815 812 BPS[0] = baseline->second.first->second; 816 813 BPS[1] = A->second; 817 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 818 814 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 815 819 816 // 4b3. insert created triangle 820 817 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); … … 825 822 LinesOnBoundaryCount++; 826 823 } 827 824 828 825 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 829 826 } else { … … 857 854 do { 858 855 flag = false; 859 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) 856 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) 860 857 if (baseline->second->TrianglesCount == 1) { 861 *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl; 858 *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl; 862 859 // 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) 863 860 SmallestAngle = M_PI; … … 888 885 TempVector.CopyVector(&CenterVector); 889 886 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 890 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 887 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 891 888 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 892 889 PropagationVector.Scale(-1.); … … 895 892 *out << endl; 896 893 winner = PointsOnBoundary.end(); 897 for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) 894 for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) 898 895 if ((target->second != baseline->second->endpoints[0]) && (target->second != baseline->second->endpoints[1])) { // don't take the same endpoints 899 896 *out << Verbose(3) << "Target point is " << *(target->second) << ":"; 900 897 bool continueflag = true; 901 898 902 899 VirtualNormalVector.CopyVector(&baseline->second->endpoints[0]->node->x); 903 900 VirtualNormalVector.AddVector(&baseline->second->endpoints[0]->node->x); … … 935 932 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 936 933 continueflag = continueflag && (!( 937 ((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 934 ((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 938 935 && (GetCommonEndpoint(LineChecker[0]->second, LineChecker[1]->second) == peak)) 939 936 )); … … 990 987 *out << Verbose(1) << "I could not determine a winner for this baseline " << *(baseline->second) << "." << endl; 991 988 } 992 989 993 990 // 5d. If the set of lines is not yet empty, go to 5. and continue 994 991 } else 995 992 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl; 996 993 } while (flag); 997 994 998 995 }; 999 996 … … 1021 1018 //==================================================================================================================== 1022 1019 1023 1024 void Find_next_suitable_point(atom a, atom b, atom Candidate, int n, Vector *d1, Vector *d2, double *Storage, const double RADIUS, molecule mol) 1025 { 1026 /* d2 ist der Normalenvektor auf dem Dreieck, 1027 * d1 ist der Vektor, der normal auf der Kante und d2 steht. 1020 /*! 1021 * This recursive function finds a third point, to form a triangle with two given ones. 1022 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1023 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1024 * upon which we operate. 1025 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its id, its general \ 1026 * direction and angle into Storage. 1027 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1028 * with all neighbours of the candidate. 1029 */ 1030 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, int n, Vector *Chord, Vector *d1, Vector *d2, double *Storage, const double RADIUS, molecule* mol) 1031 { 1032 /* d2 is normal vector on the triangle 1033 * d1 is normal on the triangle line, from which we come, as well as on d2. 1028 1034 */ 1029 Vector dif_a; 1030 Vector dif_b; 1031 Vector Chord; 1032 Vector AngleCheck; 1033 atom *Walker; 1034 1035 dif_a.CopyVector(&a.x); 1036 dif_a.SubtractVector(&Candidate.x); 1037 dif_b.CopyVector(&b.x); 1038 dif_b.SubtractVector(&Candidate.x); 1039 Chord.CopyVector(&a.x); 1040 Chord.SubtractVector(&b.x); 1035 Vector dif_a; //Vector from a to candidate 1036 Vector dif_b; //Vector from b to candidate 1037 Vector AngleCheck; // Projection of a difference vector on plane orthogonal on triangle side. 1038 atom *Walker; // variable atom point 1039 1040 dif_a.CopyVector(&(a->x)); 1041 dif_a.SubtractVector(&(Candidate->x)); 1042 dif_b.CopyVector(&(b->x)); 1043 dif_b.SubtractVector(&(Candidate->x)); 1041 1044 AngleCheck.CopyVector(&dif_a); 1042 AngleCheck.ProjectOntoPlane(&Chord); 1043 1044 //Storage eintrag fuer aktuelles Atom 1045 if (Chord.Norm()/(2*sin(dif_a.Angle(&dif_b)))<RADIUS) //Using Formula for relation of chord length with inner angle to find of Ball will touch atom 1045 AngleCheck.ProjectOntoPlane(Chord); 1046 1047 if (Chord->Norm()/(2*sin(dif_a.Angle(&dif_b)))<RADIUS) //Using Formula for relation of chord length with inner angle to find of Ball will touch atom 1046 1048 { 1047 1049 1048 1050 if (dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1))>Storage[1]) //This will give absolute preference to those in "right-hand" quadrants 1049 1051 { 1050 Storage[0]=(double)Candidate.nr;1051 Storage[1]=1;1052 Storage[2]=AngleCheck.Angle(d2);1052 Storage[0]=(double)Candidate->nr; 1053 Storage[1]=dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)); 1054 Storage[2]=AngleCheck.Angle(d2); 1053 1055 } 1054 1056 else … … 1058 1060 //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first. 1059 1061 { 1060 Storage[0]=(double)Candidate .nr;1062 Storage[0]=(double)Candidate->nr; 1061 1063 Storage[1]=dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)); 1062 1064 Storage[2]=AngleCheck.Angle(d2); … … 1065 1067 } 1066 1068 1067 if (n<5) 1068 { 1069 for(int i=0; i<mol .NumberOfBondsPerAtom[Candidate.nr];i++)1069 if (n<5) // Five is the recursion level threshold. 1070 { 1071 for(int i=0; i<mol->NumberOfBondsPerAtom[Candidate->nr];i++) // go through all bond 1070 1072 { 1071 while (Candidate.nr != (mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr ==Candidate.nr ? mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr : mol.ListOfBondsPerAtom[Candidate.nr][i]->rightatom->nr)) 1072 { 1073 Walker= mol->start; // go through all atoms 1074 1075 while (Walker->nr != (mol->ListOfBondsPerAtom[Candidate->nr][i]->leftatom->nr ==Candidate->nr ? mol->ListOfBondsPerAtom[Candidate->nr][i]->rightatom->nr : mol->ListOfBondsPerAtom[Candidate->nr][i]->leftatom->nr)) 1076 { // until atom found which belongs to bond 1073 1077 Walker = Walker->next; 1074 1078 } 1075 1079 1076 Find_next_suitable_point(a, b, *Walker, n+1, d1, d2, Storage, RADIUS, mol); 1080 1081 Find_next_suitable_point(a, b, Walker, n+1, Chord, d1, d2, Storage, RADIUS, mol); //call function again 1077 1082 } 1078 1083 } 1079 1084 }; 1080 1085 1081 1082 void Tesselation::Find_next_suitable_triangle(molecule *mol, BoundaryLineSet Line, BoundaryTriangleSet T, const double& RADIUS) 1083 { 1084 Vector CenterOfLine = Line.endpoints[0]->node->x; 1086 /*! 1087 * this function fins a triangle to a line, adjacent to an existing one. 1088 */ 1089 void Tesselation::Find_next_suitable_triangle(molecule* mol, BoundaryLineSet Line, BoundaryTriangleSet T, const double& RADIUS) 1090 { 1091 printf("Looking for next suitable triangle \n"); 1085 1092 Vector direction1; 1086 Vector direction2;1087 1093 Vector helper; 1094 Vector Chord; 1088 1095 atom* Walker; 1089 1096 1090 double Storage[3]; 1097 double *Storage; 1098 Storage = new double[3]; 1091 1099 Storage[0]=-1.; // Id must be positive, we see should nothing be done 1092 1100 Storage[1]=-1.; // This direction is either +1 or -1 one, so any result will take precedence over initial values 1093 1101 Storage[2]=-10.; // This is also lower then any value produced by an eligible atom, which are all positive 1094 1102 1095 1103 1096 1104 helper.CopyVector(&(Line.endpoints[0]->node->x)); 1097 1105 for (int i =0; i<3; i++) … … 1114 1122 } 1115 1123 1116 Find_next_suitable_point(*Line.endpoints[0]->node, *Line.endpoints[1]->node, *Line.endpoints[0]->node, 0, &direction1, T.NormalVector, Storage, RADIUS, *mol); 1117 1124 Chord.CopyVector(&(Line.endpoints[0]->node->x)); // bring into calling function 1125 Chord.SubtractVector(&(Line.endpoints[1]->node->x)); 1126 1127 printf("Looking for third point candidates for triangle \n"); 1128 Find_next_suitable_point(Line.endpoints[0]->node, Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1, T.NormalVector, Storage, RADIUS, mol); 1129 1118 1130 // Konstruiere nun neues Dreieck am Ende der Liste der Dreiecke 1119 1131 // Next Triangle is Line, atom with number in Storage[0] … … 1141 1153 for(int i=0;i<NDIM;i++) // sind Linien bereits vorhanden ??? 1142 1154 { 1143 if (LinesOnBoundary.find(BTS->lines[i]) == LinesOnBoundary.end) 1155 1156 1157 if ( (LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]))).second); 1144 1158 { 1145 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) ); 1146 LinesOnBoundaryCount++; 1159 LinesOnBoundaryCount++; 1147 1160 } 1148 1161 } … … 1154 1167 BTS->NormalVector->Scale(-1); 1155 1168 } 1156 1157 }; 1158 1159 1160 void Find_second_point_for_Tesselation(atom a, atom Candidate, int n, Vector Oben, double* Storage, molecule mol) 1161 { 1169 1170 }; 1171 1172 1173 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, int n, Vector Oben, double Storage[3], molecule* mol) 1174 { 1175 printf("Looking for second point of starting triangle \n"); 1162 1176 int i; 1163 1177 Vector *AngleCheck; 1164 1178 atom* Walker; 1165 1179 1166 AngleCheck->CopyVector(&Candidate.x); 1167 AngleCheck->SubtractVector(&a.x); 1168 if (AngleCheck->ScalarProduct(&Oben) < Storage[1]) 1169 { 1170 Storage[0]=(double)(Candidate.nr); 1171 Storage[1]=AngleCheck->ScalarProduct(&Oben); 1180 AngleCheck->CopyVector(&(Candidate->x)); 1181 AngleCheck->SubtractVector(&(a->x)); 1182 if (AngleCheck->Angle(&Oben) < Storage[1]) 1183 { 1184 //printf("Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 1185 Storage[0]=(double)(Candidate->nr); 1186 Storage[1]=AngleCheck->Angle(&Oben); 1187 //printf("Changing something in Storage: %lf %lf. \n", Storage[0], Storage[1]); 1172 1188 }; 1173 1189 printf("%d \n", n); 1174 1190 if (n<5) 1175 1191 { 1176 for (i = 0; i< mol .NumberOfBondsPerAtom[Candidate.nr]; i++)1192 for (i = 0; i< mol->NumberOfBondsPerAtom[Candidate->nr]; i++) 1177 1193 { 1178 Walker = mol .start;1179 while (Candidate .nr != (mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr ==Candidate.nr ? mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr : mol.ListOfBondsPerAtom[Candidate.nr][i]->rightatom->nr))1194 Walker = mol->start; 1195 while (Candidate->nr != (mol->ListOfBondsPerAtom[Candidate->nr][i]->leftatom->nr ==Candidate->nr ? mol->ListOfBondsPerAtom[Candidate->nr][i]->leftatom->nr : mol->ListOfBondsPerAtom[Candidate->nr][i]->rightatom->nr)) 1180 1196 { 1181 1197 Walker = Walker->next; 1182 1198 }; 1183 1184 Find_second_point_for_Tesselation(a, *Walker, n+1, Oben, Storage, mol);1199 1200 Find_second_point_for_Tesselation(a, Walker, n+1, Oben, Storage, mol); 1185 1201 }; 1186 1202 }; 1187 1188 1189 }; 1190 1191 1192 void Tesselation::Find_starting_triangle(molecule mol, const double RADIUS) 1193 { 1203 1204 1205 }; 1206 1207 1208 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS) 1209 { 1210 printf("Looking for starting triangle \n"); 1194 1211 int i=0; 1195 atom Walker;1196 atom Walker2;1197 atom Walker3;1212 atom* Walker; 1213 atom* Walker2; 1214 atom* Walker3; 1198 1215 int max_index[3]; 1199 1216 double max_coordinate[3]; 1200 1217 Vector Oben; 1201 1218 Vector helper; 1219 Vector Chord; 1202 1220 1203 1221 Oben.Zero(); … … 1209 1227 max_coordinate[i] =-1; 1210 1228 } 1211 1212 Walker = *mol.start; 1213 while (Walker.next != NULL) 1214 { 1229 printf("Molecule mol is there and has %d Atoms \n", mol->AtomCount); 1230 Walker = mol->start; 1231 while (Walker->next != mol->end) 1232 { 1233 Walker = Walker->next; 1215 1234 for (i=0; i<3; i++) 1216 {1217 if (Walker .x.x[i]>max_coordinate[i])1235 { 1236 if (Walker->x.x[i] > max_coordinate[i]) 1218 1237 { 1219 max_coordinate[i]=Walker .x.x[i];1220 max_index[i]=Walker .nr;1238 max_coordinate[i]=Walker->x.x[i]; 1239 max_index[i]=Walker->nr; 1221 1240 } 1222 } 1223 } 1224 1241 } 1242 } 1243 1244 printf("Found starting atom \n"); 1225 1245 //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0 1226 const int k=0; 1227 1228 Oben.x[k]=1; 1229 Walker = *mol.start; 1230 while (Walker.nr != max_index[k]) 1231 { 1232 Walker = *Walker.next; 1233 } 1234 1246 const int k=2; 1247 1248 Oben.x[k]=1.; 1249 Walker = mol->start; 1250 Walker = Walker->next; 1251 while (Walker->nr != max_index[k]) 1252 { 1253 Walker = Walker->next; 1254 } 1255 printf("%d \n", Walker->nr); 1235 1256 double Storage[3]; 1236 1257 Storage[0]=-1.; // Id must be positive, we see should nothing be done 1237 Storage[1]=-2.; // 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. 1238 Storage[2]=-10.; // This will be an angle looking for the third point. 1239 1240 1241 for (i=0; i< mol.NumberOfBondsPerAtom[Walker.nr]; i++) 1242 { 1243 Walker2 = *mol.start; 1244 while (Walker2.nr != (mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom->nr == Walker.nr ? mol.ListOfBondsPerAtom[Walker.nr][i]->rightatom->nr : mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom->nr) ) 1258 Storage[1]=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. 1259 Storage[2]=999999.; // This will be an angle looking for the third point. 1260 printf("%d \n", mol->NumberOfBondsPerAtom[Walker->nr]); 1261 1262 for (i=1; i< (mol->NumberOfBondsPerAtom[Walker->nr]); i++) 1263 { 1264 Walker2 = mol->start; 1265 Walker2 = Walker2->next; 1266 while (Walker2->nr != (mol->ListOfBondsPerAtom[Walker->nr][i]->leftatom->nr == Walker->nr ? mol->ListOfBondsPerAtom[Walker->nr][i]->rightatom->nr : mol->ListOfBondsPerAtom[Walker->nr][i]->leftatom->nr) ) 1245 1267 { 1246 Walker2 = *Walker2.next;1268 Walker2 = Walker2->next; 1247 1269 } 1248 1270 … … 1250 1272 } 1251 1273 1252 Walker2 = *mol.start;1253 1254 while (Walker2 .nr != int(Storage[0]))1255 { 1256 Walker = *Walker.next;1257 } 1258 1259 helper.CopyVector(& Walker.x);1260 helper.SubtractVector(& Walker2.x);1274 Walker2 = mol->start; 1275 1276 while (Walker2->nr != int(Storage[0])) 1277 { 1278 Walker2 = Walker2->next; 1279 } 1280 1281 helper.CopyVector(&(Walker->x)); 1282 helper.SubtractVector(&(Walker2->x)); 1261 1283 Oben.ProjectOntoPlane(&helper); 1262 1284 helper.VectorProduct(&Oben); 1263 1264 Find_next_suitable_point(Walker, Walker2, *(mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom->nr == Walker.nr ? mol.ListOfBondsPerAtom[Walker.nr][i]->rightatom : mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom), 0, &helper, &Oben, Storage, RADIUS, mol); 1265 Walker3 = *mol.start; 1266 while (Walker3.nr != int(Storage[0])) 1267 { 1268 Walker3 = *Walker3.next; 1285 Storage[0]=-1.; // Id must be positive, we see should nothing be done 1286 Storage[1]=-2.; // 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. 1287 Storage[2]= -10.; // This will be an angle looking for the third point. 1288 1289 Chord.CopyVector(&(Walker->x)); // bring into calling function 1290 Chord.SubtractVector(&(Walker2->x)); 1291 1292 printf("Looking for third point candidates \n"); 1293 Find_next_suitable_point(Walker, Walker2, (mol->ListOfBondsPerAtom[Walker->nr][0]->leftatom->nr == Walker->nr ? mol->ListOfBondsPerAtom[Walker->nr][0]->rightatom : mol->ListOfBondsPerAtom[Walker->nr][0]->leftatom), 0, &Chord, &helper, &Oben, Storage, RADIUS, mol); 1294 Walker3 = mol->start; 1295 while (Walker3->nr != int(Storage[0])) 1296 { 1297 Walker3 = Walker3->next; 1269 1298 } 1270 1299 1271 1300 //Starting Triangle is Walker, Walker2, index Storage[0] 1272 1301 1273 AddPoint( &Walker);1274 AddPoint( &Walker2);1275 AddPoint( &Walker3);1276 1277 BPS[0] = new class BoundaryPointSet( &Walker);1278 BPS[1] = new class BoundaryPointSet( &Walker2);1302 AddPoint(Walker); 1303 AddPoint(Walker2); 1304 AddPoint(Walker3); 1305 1306 BPS[0] = new class BoundaryPointSet(Walker); 1307 BPS[1] = new class BoundaryPointSet(Walker2); 1279 1308 BLS[0] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1280 BPS[0] = new class BoundaryPointSet( &Walker);1281 BPS[1] = new class BoundaryPointSet( &Walker3);1309 BPS[0] = new class BoundaryPointSet(Walker); 1310 BPS[1] = new class BoundaryPointSet(Walker3); 1282 1311 BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1283 BPS[0] = new class BoundaryPointSet( &Walker);1284 BPS[1] = new class BoundaryPointSet( &Walker2);1285 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1312 BPS[0] = new class BoundaryPointSet(Walker); 1313 BPS[1] = new class BoundaryPointSet(Walker2); 1314 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1286 1315 1287 1316 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); … … 1289 1318 TrianglesOnBoundaryCount++; 1290 1319 1291 for(int i=0;i<NDIM;i++) 1320 for(int i=0;i<NDIM;i++) 1292 1321 { 1293 1322 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) ); … … 1304 1333 1305 1334 1306 void Find_non_convex_border(Tesselation* Tess, molecule mol) 1307 { 1335 void Find_non_convex_border(Tesselation Tess, molecule* mol) 1336 { 1337 printf("Entering finding of non convex hull. \n"); 1308 1338 const double RADIUS =6; 1309 Tess ->Find_starting_triangle(mol, RADIUS);1310 1311 for (LineMap::iterator baseline = Tess ->LinesOnBoundary.begin(); baseline != Tess->LinesOnBoundary.end(); baseline++)1312 if (baseline->second->TrianglesCount == 1) 1339 Tess.Find_starting_triangle(mol, RADIUS); 1340 1341 for (LineMap::iterator baseline = Tess.LinesOnBoundary.begin(); baseline != Tess.LinesOnBoundary.end(); baseline++) 1342 if (baseline->second->TrianglesCount == 1) 1313 1343 { 1314 Tess->Find_next_suitable_triangle(&mol, baseline->second, baseline->second->triangles.begin()->second, RADIUS); //the line is there, so there is a triangle, but only one. 1315 1344 Tess.Find_next_suitable_triangle(mol, *(baseline->second), *(baseline->second->triangles.begin()->second), RADIUS); //the line is there, so there is a triangle, but only one. 1316 1345 } 1317 1346 else
Note:
See TracChangeset
for help on using the changeset viewer.
