Changeset 4e4940 for molecuilder/src/boundary.cpp
- Timestamp:
- Aug 3, 2009, 8:10:09 AM (16 years ago)
- Children:
- 0e2190, 834ff3
- Parents:
- 3dc682
- File:
-
- 1 edited
-
molecuilder/src/boundary.cpp (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
molecuilder/src/boundary.cpp
r3dc682 r4e4940 132 132 ; 133 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 134 188 ostream & 135 189 operator <<(ostream &ost, BoundaryLineSet &a) … … 214 268 ; 215 269 216 void 217 BoundaryTriangleSet::GetNormalVector(Vector &OtherVector) 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) 218 275 { 219 276 // get normal vector … … 224 281 if (NormalVector.Projection(&OtherVector) > 0) 225 282 NormalVector.Scale(-1.); 226 } 227 ; 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 }; 228 355 229 356 ostream & … … 774 901 TesselStruct->TesselateOnBoundary(out, mol); 775 902 776 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount << " triangles with " << TesselStruct->LinesOnBoundaryCount << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." << endl; 903 // 3c. check whether all atoms lay inside the boundary, if not, add to boundary points, segment triangle into three with the new point 904 if (!TesselStruct->InsertStraddlingPoints(out, mol)) 905 *out << Verbose(1) << "Insertion of straddling points failed!" << endl; 906 907 // 3d. check all baselines whether the peaks of the two adjacent triangles with respect to center of baseline are convex, if not, make the baseline between the two peaks and baseline endpoints become the new peaks 908 if (!TesselStruct->CorrectConcaveBaselines(out)) 909 *out << Verbose(1) << "Correction of concave baselines failed!" << endl; 910 911 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundary.size() << " triangles with " << TesselStruct->LinesOnBoundary.size() << " lines and " << TesselStruct->PointsOnBoundary.size() << " points." << endl; 777 912 778 913 // 4. Store triangles in tecplot file … … 980 1115 } 981 1116 ; 1117 1118 1119 /** Fills the empty space of the simulation box with water/ 1120 * \param *out output stream for debugging 1121 * \param *List list of molecules already present in box 1122 * \param *TesselStruct contains tesselated surface 1123 * \param *filler molecule which the box is to be filled with 1124 * \param configuration contains box dimensions 1125 * \param distance[NDIM] distance between filling molecules in each direction 1126 * \param RandAtomDisplacement maximum distance for random displacement per atom 1127 * \param RandMolDisplacement maximum distance for random displacement per filler molecule 1128 * \param DoRandomRotation true - do random rotiations, false - don't 1129 * \return *mol pointer to new molecule with filled atoms 1130 */ 1131 molecule * FillBoxWithMolecule(ofstream *out, MoleculeListClass *List, molecule *filler, config &configuration, double distance[NDIM], double RandomAtomDisplacement, double RandomMolDisplacement, bool DoRandomRotation) 1132 { 1133 molecule *Filling = new molecule(filler->elemente); 1134 Vector CurrentPosition; 1135 int N[NDIM]; 1136 int n[NDIM]; 1137 double *M = filler->ReturnFullMatrixforSymmetric(filler->cell_size); 1138 double Rotations[NDIM*NDIM]; 1139 Vector AtomTranslations; 1140 Vector FillerTranslations; 1141 Vector FillerDistance; 1142 double FillIt = false; 1143 atom *Walker = NULL, *Runner = NULL; 1144 bond *Binder = NULL; 1145 1146 // Center filler at origin 1147 filler->CenterOrigin(out); 1148 filler->Center.Zero(); 1149 1150 // calculate filler grid in [0,1]^3 1151 FillerDistance.Init(distance[0], distance[1], distance[2]); 1152 FillerDistance.InverseMatrixMultiplication(M); 1153 for(int i=0;i<NDIM;i++) 1154 N[i] = ceil(1./FillerDistance.x[i]); 1155 1156 // go over [0,1]^3 filler grid 1157 for (n[0] = 0; n[0] < N[0]; n[0]++) 1158 for (n[1] = 0; n[1] < N[1]; n[1]++) 1159 for (n[2] = 0; n[2] < N[2]; n[2]++) { 1160 // calculate position of current grid vector in untransformed box 1161 CurrentPosition.Init(n[0], n[1], n[2]); 1162 CurrentPosition.MatrixMultiplication(M); 1163 // Check whether point is in- or outside 1164 FillIt = true; 1165 for (MoleculeList::iterator ListRunner = List->ListOfMolecules.begin(); ListRunner != List->ListOfMolecules.end(); ListRunner++) { 1166 FillIt = FillIt && (!(*ListRunner)->TesselStruct->IsInside(&CurrentPosition)); 1167 } 1168 1169 if (FillIt) { 1170 // fill in Filler 1171 *out << Verbose(2) << "Space at " << CurrentPosition << " is unoccupied by any molecule, filling in." << endl; 1172 1173 // create molecule random translation vector ... 1174 for (int i=0;i<NDIM;i++) 1175 FillerTranslations.x[i] = RandomMolDisplacement*(rand()/(RAND_MAX/2.) - 1.); 1176 1177 // go through all atoms 1178 Walker = filler->start; 1179 while (Walker != filler->end) { 1180 Walker = Walker->next; 1181 // copy atom ... 1182 *Runner = new atom(Walker); 1183 1184 // create atomic random translation vector ... 1185 for (int i=0;i<NDIM;i++) 1186 AtomTranslations.x[i] = RandomAtomDisplacement*(rand()/(RAND_MAX/2.) - 1.); 1187 1188 // ... and rotation matrix 1189 if (DoRandomRotation) { 1190 double phi[NDIM]; 1191 for (int i=0;i<NDIM;i++) { 1192 phi[i] = rand()/(RAND_MAX/(2.*M_PI)); 1193 } 1194 1195 Rotations[0] = cos(phi[0]) *cos(phi[2]) + (sin(phi[0])*sin(phi[1])*sin(phi[2])); 1196 Rotations[3] = sin(phi[0]) *cos(phi[2]) - (cos(phi[0])*sin(phi[1])*sin(phi[2])); 1197 Rotations[6] = cos(phi[1])*sin(phi[2]) ; 1198 Rotations[1] = - sin(phi[0])*cos(phi[1]) ; 1199 Rotations[4] = cos(phi[0])*cos(phi[1]) ; 1200 Rotations[7] = sin(phi[1]) ; 1201 Rotations[3] = - cos(phi[0]) *sin(phi[2]) + (sin(phi[0])*sin(phi[1])*cos(phi[2])); 1202 Rotations[5] = - sin(phi[0]) *sin(phi[2]) - (cos(phi[0])*sin(phi[1])*cos(phi[2])); 1203 Rotations[8] = cos(phi[1])*cos(phi[2]) ; 1204 } 1205 1206 // ... and put at new position 1207 if (DoRandomRotation) 1208 Runner->x.MatrixMultiplication(Rotations); 1209 Runner->x.AddVector(&AtomTranslations); 1210 Runner->x.AddVector(&FillerTranslations); 1211 Runner->x.AddVector(&CurrentPosition); 1212 // insert into Filling 1213 Filling->AddAtom(Runner); 1214 } 1215 1216 // go through all bonds and add as well 1217 Binder = filler->first; 1218 while(Binder != filler->last) { 1219 Binder = Binder->next; 1220 } 1221 } else { 1222 // leave empty 1223 *out << Verbose(2) << "Space at " << CurrentPosition << " is occupied." << endl; 1224 } 1225 } 1226 return Filling; 1227 }; 1228 982 1229 983 1230 // =========================================================== class TESSELATION =========================================== … … 1196 1443 1197 1444 MolCenter = mol->DetermineCenterOfAll(out); 1445 // create a first tesselation with the given BoundaryPoints 1198 1446 do { 1199 1447 flag = false; … … 1368 1616 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl; 1369 1617 } while (flag); 1618 1619 // exit 1370 1620 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 debugging 1625 * \param *mol molecule structure with atoms 1626 * \return true - all straddling points insert, false - something went wrong 1627 */ 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 bigger 1634 // get the next triangle 1635 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 point 1641 if (BTS->GetIntersectionInsideTriangle(out, MolCenter, &Walker->x, &Intersection)) { 1642 // we have the intersection, check whether in- or outside of boundary 1643 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 points 1652 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 points 1657 AddPoint(Walker); 1658 if (BPS[0] == NULL) 1659 NewPoint = BPS[0]; 1660 else 1661 continue; 1662 // remove triangle 1663 TrianglesOnBoundary.erase(BTS->Nr); 1664 // create three new boundary lines 1665 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 one 1670 LinesOnBoundaryCount++; 1671 } 1672 // create three new triangle with new point 1673 for (int i=0;i<3;i++) { // find all baselines 1674 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 } else 1682 BLS[n++] = NewLines[j]; 1683 } 1684 } 1685 // create the triangle 1686 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 // exit 1698 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 debugging 1704 * \return true - all baselines were corrected, false - there are still concave pieces 1705 */ 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 convexity 1719 if (Base->CheckConvexityCriterion(out)) { // triangles are convex 1720 *out << Verbose(3) << Base << " has two convex triangles." << endl; 1721 } else { // not convex! 1722 // get the two triangles 1723 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 lines 1727 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 triangles 1733 for (int j=0;j<3;j++) { // all of their endpoints and baselines 1734 if (triangle[m]->lines[j] != Base) // pick not the central baseline 1735 OldLines[i++] = triangle[m]->lines[j]; 1736 if (!Base->ContainsBoundaryPoint(triangle[m]->endpoints[j])) // and neither of its endpoints 1737 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 triangles 1756 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 baseline 1763 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 one 1772 1773 // construct new triangles with flipped baseline 1774 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 checked 1803 * \return true - is inside, false - is outside 1804 */ 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 debugging 1815 * \param *x second endpoint of line 1816 * \return pointer triangle that is closest, NULL if none was found 1817 */ 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; 1371 1825 }; 1372 1826 … … 1382 1836 if (InsertUnique.second) // if new point was not present before, increase counter 1383 1837 PointsOnBoundaryCount++; 1838 else { 1839 delete(BPS[0]); 1840 BPS[0] = NULL; 1841 } 1384 1842 } 1385 1843 ;
Note:
See TracChangeset
for help on using the changeset viewer.
