Changeset 60cbe5 for molecuilder/src/tesselation.cpp
- Timestamp:
- Sep 28, 2009, 8:00:33 PM (16 years ago)
- Children:
- fca6e7
- Parents:
- bb56cf
- git-author:
- Frederik Heber <heber@…> (09/28/09 18:47:54)
- git-committer:
- Frederik Heber <heber@…> (09/28/09 20:00:33)
- File:
-
- 1 edited
-
molecuilder/src/tesselation.cpp (modified) (59 diffs)
Legend:
- Unmodified
- Added
- Removed
-
molecuilder/src/tesselation.cpp
rbb56cf r60cbe5 6 6 */ 7 7 8 #include "helpers.hpp" 9 #include "linkedcell.hpp" 8 10 #include "tesselation.hpp" 11 #include "tesselationhelpers.hpp" 12 #include "vector.hpp" 13 14 class molecule; 9 15 10 16 // ======================================== Points on Boundary ================================= … … 36 42 BoundaryPointSet::~BoundaryPointSet() 37 43 { 38 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;44 //cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 39 45 if (!lines.empty()) 40 46 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl; … … 66 72 ostream & operator <<(ostream &ost, BoundaryPointSet &a) 67 73 { 68 ost << "[" << a.Nr << "|" << a.node->Name << " ]";74 ost << "[" << a.Nr << "|" << a.node->Name << " at " << *a.node->node << "]"; 69 75 return ost; 70 76 } … … 124 130 for (LineMap::iterator Runner = erasor.first; Runner != erasor.second; Runner++) 125 131 if ((*Runner).second == this) { 126 cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;132 //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 127 133 endpoints[i]->lines.erase(Runner); 128 134 break; 129 135 } 130 136 } else { // there's just a single line left 131 if (endpoints[i]->lines.erase(Nr)) 132 cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 137 if (endpoints[i]->lines.erase(Nr)) { 138 //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 139 } 133 140 } 134 141 if (endpoints[i]->lines.empty()) { 135 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;142 //cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 136 143 if (endpoints[i] != NULL) { 137 144 delete(endpoints[i]); … … 167 174 168 175 /** Checks whether the adjacent triangles of a baseline are convex or not. 169 * We sum the two angles of each normal vector with a ficticious normnal vector from this baselinbe pointing outwards.176 * We sum the two angles of each height vector with respect to the center of the baseline. 170 177 * If greater/equal M_PI than we are convex. 171 178 * \param *out output stream for debugging … … 177 184 // get the two triangles 178 185 if (triangles.size() != 2) { 179 *out << Verbose(1) << "ERROR: Baseline " << *this << " is connect to less than two triangles, Tesselation incomplete!" << endl;186 *out << Verbose(1) << "ERROR: Baseline " << *this << " is connected to less than two triangles, Tesselation incomplete!" << endl; 180 187 return true; 181 188 } … … 200 207 NormalCheck.Scale(sign); 201 208 sign = -sign; 202 BaseLineNormal.SubtractVector(&runner->second->NormalVector); // we subtract as BaseLineNormal has to point inward in direction of [pi,2pi] 209 if (runner->second->NormalVector.NormSquared() > MYEPSILON) 210 BaseLineNormal.CopyVector(&runner->second->NormalVector); // yes, copy second on top of first 211 else { 212 *out << Verbose(1) << "CRITICAL: Triangle " << *runner->second << " has zero normal vector!" << endl; 213 exit(255); 214 } 203 215 node = runner->second->GetThirdEndpoint(this); 204 216 if (node != NULL) { 205 //*out << Verbose(3) << "INFO: Third node for triangle " << *(runner->second) << " is " << *node << " at " << *(node->node->node) << "." << endl;217 *out << Verbose(3) << "INFO: Third node for triangle " << *(runner->second) << " is " << *node << " at " << *(node->node->node) << "." << endl; 206 218 helper[i].CopyVector(node->node->node); 207 219 helper[i].SubtractVector(&BaseLineCenter); 208 220 helper[i].MakeNormalVector(&BaseLine); // we want to compare the triangle's heights' angles! 209 //*out << Verbose(4) << "INFO: Height vector with respect to baseline is " << helper[i] << "." << endl;221 *out << Verbose(4) << "INFO: Height vector with respect to baseline is " << helper[i] << "." << endl; 210 222 i++; 211 223 } else { 212 //*out << Verbose(2) << " WARNING: I cannot find third node in triangle, something's wrong." << endl;224 //*out << Verbose(2) << "ERROR: I cannot find third node in triangle, something's wrong." << endl; 213 225 return true; 214 226 } 215 227 } 216 //*out << Verbose(3) << "INFO: BaselineNormal is " << BaseLineNormal << "." << endl;228 *out << Verbose(3) << "INFO: BaselineNormal is " << BaseLineNormal << "." << endl; 217 229 if (NormalCheck.NormSquared() < MYEPSILON) { 218 *out << Verbose( 2) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl;230 *out << Verbose(3) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl; 219 231 return true; 220 232 } 233 BaseLineNormal.Scale(-1.); 221 234 double angle = GetAngle(helper[0], helper[1], BaseLineNormal); 222 235 if ((angle - M_PI) > -MYEPSILON) { 223 *out << Verbose( 2) << "ACCEPT: Angle is greater than pi: convex." << endl;236 *out << Verbose(3) << "ACCEPT: Angle is greater than pi: convex." << endl; 224 237 return true; 225 238 } else { 226 *out << Verbose( 2) << "REJECT: Angle is less than pi: concave." << endl;239 *out << Verbose(3) << "REJECT: Angle is less than pi: concave." << endl; 227 240 return false; 228 241 } … … 261 274 ostream & operator <<(ostream &ost, BoundaryLineSet &a) 262 275 { 263 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " ," << a.endpoints[1]->node->Name << "]";276 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " at " << *a.endpoints[0]->node->node << "," << a.endpoints[1]->node->Name << " at " << *a.endpoints[1]->node->node << "]"; 264 277 return ost; 265 278 }; … … 331 344 for (int i = 0; i < 3; i++) { 332 345 if (lines[i] != NULL) { 333 if (lines[i]->triangles.erase(Nr)) 334 cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl; 346 if (lines[i]->triangles.erase(Nr)) { 347 //cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl; 348 } 335 349 if (lines[i]->triangles.empty()) { 336 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;350 //cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 337 351 delete (lines[i]); 338 352 lines[i] = NULL; … … 340 354 } 341 355 } 342 cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl;356 //cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl; 343 357 }; 344 358 … … 450 464 }; 451 465 466 /** Checks whether three given \a *Points coincide with triangle's endpoints. 467 * \param *Points[3] pointer to BoundaryPointSet 468 * \return true - is the very triangle, false - is not 469 */ 470 bool BoundaryTriangleSet::IsPresentTupel(class BoundaryTriangleSet *T) 471 { 472 return (((endpoints[0] == T->endpoints[0]) 473 || (endpoints[0] == T->endpoints[1]) 474 || (endpoints[0] == T->endpoints[2]) 475 ) && ( 476 (endpoints[1] == T->endpoints[0]) 477 || (endpoints[1] == T->endpoints[1]) 478 || (endpoints[1] == T->endpoints[2]) 479 ) && ( 480 (endpoints[2] == T->endpoints[0]) 481 || (endpoints[2] == T->endpoints[1]) 482 || (endpoints[2] == T->endpoints[2]) 483 484 )); 485 }; 486 452 487 /** Returns the endpoint which is not contained in the given \a *line. 453 488 * \param *line baseline defining two endpoints … … 484 519 ostream &operator <<(ostream &ost, BoundaryTriangleSet &a) 485 520 { 486 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " ,"487 << a.endpoints[1]->node->Name << " ," << a.endpoints[2]->node->Name << "]";521 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " at " << *a.endpoints[0]->node->node << "," 522 << a.endpoints[1]->node->Name << " at " << *a.endpoints[1]->node->node << "," << a.endpoints[2]->node->Name << " at " << *a.endpoints[2]->node->node << "]"; 488 523 return ost; 489 524 }; … … 504 539 TesselPoint::~TesselPoint() 505 540 { 506 Free((void **)&Name, "TesselPoint::~TesselPoint: *Name");507 541 }; 508 542 … … 511 545 ostream & operator << (ostream &ost, const TesselPoint &a) 512 546 { 513 ost << "[" << (a.Name) << "|" << &a<< "]";547 ost << "[" << (a.Name) << "|" << a.Name << " at " << *a.node << "]"; 514 548 return ost; 515 549 }; … … 568 602 TrianglesOnBoundaryCount = 0; 569 603 InternalPointer = PointsOnBoundary.begin(); 604 LastTriangle = NULL; 605 TriangleFilesWritten = 0; 570 606 } 571 607 ; … … 584 620 cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl; 585 621 } 622 cout << "This envelope was written to file " << TriangleFilesWritten << " times(s)." << endl; 586 623 } 587 624 ; … … 1232 1269 void Tesselation::AlwaysAddTesselationTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n) 1233 1270 { 1234 cout << Verbose(4) << "Adding line between" << *(a->node) << " and " << *(b->node) << "." << endl;1271 cout << Verbose(4) << "Adding line [" << LinesOnBoundaryCount << "|" << *(a->node) << " and " << *(b->node) << "." << endl; 1235 1272 BPS[0] = a; 1236 1273 BPS[1] = b; … … 1252 1289 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1253 1290 TrianglesOnBoundaryCount++; 1291 1292 // set as last new triangle 1293 LastTriangle = BTS; 1254 1294 1255 1295 // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet … … 1524 1564 CandidateList *OptCandidates = new CandidateList(); 1525 1565 for (int k=0;k<NDIM;k++) { 1566 Oben.Zero(); 1526 1567 Oben.x[k] = 1.; 1527 1568 FirstPoint = MaxPoint[k]; … … 1532 1573 ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant. 1533 1574 1534 FindSecondPointForTesselation(FirstPoint, NULL,Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...1575 FindSecondPointForTesselation(FirstPoint, Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_... 1535 1576 SecondPoint = OptCandidate; 1536 1577 if (SecondPoint == NULL) // have we found a second point? 1537 1578 continue; 1538 else1539 cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n";1540 1579 1541 1580 helper.CopyVector(FirstPoint->node); … … 1559 1598 1560 1599 // adding point 1 and point 2 and add the line between them 1600 cout << Verbose(1) << "Coordinates of start node at " << *FirstPoint->node << "." << endl; 1561 1601 AddTesselationPoint(FirstPoint, 0); 1602 cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n"; 1562 1603 AddTesselationPoint(SecondPoint, 1); 1563 1604 AddTesselationLine(TPS[0], TPS[1], 0); … … 1632 1673 * @param *LC LinkedCell structure with neighbouring points 1633 1674 */ 1634 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N,LinkedCell *LC)1675 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, LinkedCell *LC) 1635 1676 { 1636 1677 cout << Verbose(0) << "Begin of FindNextSuitableTriangle\n"; … … 1667 1708 CircleRadius = RADIUS*RADIUS - radius/4.; 1668 1709 CirclePlaneNormal.Normalize(); 1669 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;1710 //cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 1670 1711 1671 1712 // construct old center … … 1754 1795 result = false; 1755 1796 } 1756 } else if ( existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time.1797 } else if ((existentTrianglesCount >= 1) && (existentTrianglesCount <= 3)) { // If there is a planar region within the structure, we need this triangle a second time. 1757 1798 AddTesselationPoint((*it)->point, 0); 1758 1799 AddTesselationPoint(BaseRay->endpoints[0]->node, 1); … … 1795 1836 // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point)) 1796 1837 BaseRay = BLS[0]; 1838 if ((BTS != NULL) && (BTS->NormalVector.NormSquared() < MYEPSILON)) { 1839 *out << Verbose(1) << "CRITICAL: Triangle " << *BTS << " has zero normal vector!" << endl; 1840 exit(255); 1841 } 1842 1797 1843 } 1798 1844 … … 1813 1859 * \param *out output stream for debugging 1814 1860 * \param *Base line to be flipped 1815 * \return NULL - con cave, otherwise endpoint that makes it concave1861 * \return NULL - convex, otherwise endpoint that makes it concave 1816 1862 */ 1817 1863 class BoundaryPointSet *Tesselation::IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base) … … 1890 1936 * \param *out output stream for debugging 1891 1937 * \param *Base line to be flipped 1892 * \return true - line was changed, false - same line as before1893 */ 1894 boolTesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base)1938 * \return volume change due to flipping (0 - then no flipped occured) 1939 */ 1940 double Tesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base) 1895 1941 { 1896 1942 class BoundaryLineSet *OtherBase; 1897 1943 Vector *ClosestPoint[2]; 1944 double volume; 1898 1945 1899 1946 int m=0; … … 1915 1962 Distance.CopyVector(ClosestPoint[1]); 1916 1963 Distance.SubtractVector(ClosestPoint[0]); 1964 1965 // calculate volume 1966 volume = CalculateVolumeofGeneralTetraeder(Base->endpoints[1]->node->node, OtherBase->endpoints[0]->node->node, OtherBase->endpoints[1]->node->node, Base->endpoints[0]->node->node); 1917 1967 1918 1968 // delete the temporary other base line and the closest points … … 1929 1979 if (Base->triangles.size() < 2) { 1930 1980 *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl; 1931 return false;1981 return 0.; 1932 1982 } 1933 1983 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { … … 1939 1989 if (Distance.ScalarProduct(&BaseLineNormal) > MYEPSILON) { // Distance points outwards, hence OtherBase higher than Base -> flip 1940 1990 *out << Verbose(2) << "ACCEPT: Other base line would be higher: Flipping baseline." << endl; 1941 FlipBaseline(out, Base);1942 return true;1991 // calculate volume summand as a general tetraeder 1992 return volume; 1943 1993 } else { // Base higher than OtherBase -> do nothing 1944 1994 *out << Verbose(2) << "REJECT: Base line is higher: Nothing to do." << endl; 1945 return false; 1946 } 1947 } 1948 }; 1949 1950 /** Returns the closest point on \a *Base with respect to \a *OtherBase. 1951 * \param *out output stream for debugging 1952 * \param *Base reference line 1953 * \param *OtherBase other base line 1954 * \return Vector on reference line that has closest distance 1955 */ 1956 Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase) 1957 { 1958 // construct the plane of the two baselines (i.e. take both their directional vectors) 1959 Vector Normal; 1960 Vector Baseline, OtherBaseline; 1961 Baseline.CopyVector(Base->endpoints[1]->node->node); 1962 Baseline.SubtractVector(Base->endpoints[0]->node->node); 1963 OtherBaseline.CopyVector(OtherBase->endpoints[1]->node->node); 1964 OtherBaseline.SubtractVector(OtherBase->endpoints[0]->node->node); 1965 Normal.CopyVector(&Baseline); 1966 Normal.VectorProduct(&OtherBaseline); 1967 Normal.Normalize(); 1968 *out << Verbose(4) << "First direction is " << Baseline << ", second direction is " << OtherBaseline << ", normal of intersection plane is " << Normal << "." << endl; 1969 1970 // project one offset point of OtherBase onto this plane (and add plane offset vector) 1971 Vector NewOffset; 1972 NewOffset.CopyVector(OtherBase->endpoints[0]->node->node); 1973 NewOffset.SubtractVector(Base->endpoints[0]->node->node); 1974 NewOffset.ProjectOntoPlane(&Normal); 1975 NewOffset.AddVector(Base->endpoints[0]->node->node); 1976 Vector NewDirection; 1977 NewDirection.CopyVector(&NewOffset); 1978 NewDirection.AddVector(&OtherBaseline); 1979 1980 // calculate the intersection between this projected baseline and Base 1981 Vector *Intersection = new Vector; 1982 Intersection->GetIntersectionOfTwoLinesOnPlane(out, Base->endpoints[0]->node->node, Base->endpoints[1]->node->node, &NewOffset, &NewDirection, &Normal); 1983 Normal.CopyVector(Intersection); 1984 Normal.SubtractVector(Base->endpoints[0]->node->node); 1985 *out << Verbose(3) << "Found closest point on " << *Base << " at " << *Intersection << ", factor in line is " << fabs(Normal.ScalarProduct(&Baseline)/Baseline.NormSquared()) << "." << endl; 1986 1987 return Intersection; 1995 return 0.; 1996 } 1997 } 1988 1998 }; 1989 1999 … … 1993 2003 * \param *out output stream for debugging 1994 2004 * \param *Base line to be flipped 1995 * \return true - flipping successful, false- something went awry1996 */ 1997 boolTesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base)2005 * \return pointer to allocated new baseline - flipping successful, NULL - something went awry 2006 */ 2007 class BoundaryLineSet * Tesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base) 1998 2008 { 1999 2009 class BoundaryLineSet *OldLines[4], *NewLine; … … 2009 2019 if (Base->triangles.size() < 2) { 2010 2020 *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl; 2011 return false;2021 return NULL; 2012 2022 } 2013 2023 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { … … 2045 2055 if (i<4) { 2046 2056 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl; 2047 return false;2057 return NULL; 2048 2058 } 2049 2059 for (int j=0;j<4;j++) 2050 2060 if (OldLines[j] == NULL) { 2051 2061 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl; 2052 return false;2062 return NULL; 2053 2063 } 2054 2064 for (int j=0;j<2;j++) 2055 2065 if (OldPoints[j] == NULL) { 2056 2066 *out << Verbose(1) << "ERROR: We have not gathered enough endpoints!" << endl; 2057 return false;2067 return NULL; 2058 2068 } 2059 2069 … … 2099 2109 } else { 2100 2110 *out << Verbose(1) << "The four old lines do not connect, something's utterly wrong here!" << endl; 2101 return false;2111 return NULL; 2102 2112 } 2103 2113 2104 2114 *out << Verbose(1) << "End of FlipBaseline" << endl; 2105 return true;2115 return NewLine; 2106 2116 }; 2107 2117 … … 2109 2119 /** Finds the second point of starting triangle. 2110 2120 * \param *a first node 2111 * \param *Candidate pointer to candidate node on return2112 2121 * \param Oben vector indicating the outside 2113 2122 * \param OptCandidate reference to recommended candidate on return … … 2116 2125 * \param *LC LinkedCell structure with neighbouring points 2117 2126 */ 2118 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, TesselPoint* Candidate,Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC)2127 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC) 2119 2128 { 2120 2129 cout << Verbose(2) << "Begin of FindSecondPointForTesselation" << endl; 2121 2130 Vector AngleCheck; 2131 class TesselPoint* Candidate = NULL; 2122 2132 double norm = -1., angle; 2123 2133 LinkedNodes *List = NULL; … … 2254 2264 cout << Verbose(1) << "Begin of FindThirdPointForTesselation" << endl; 2255 2265 2256 //cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;2266 cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl; 2257 2267 2258 2268 // construct center of circle … … 2279 2289 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2280 2290 if (fabs(radius - CircleRadius) < HULLEPSILON) { 2291 //cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl; 2281 2292 2282 2293 // check SearchDirection … … 2455 2466 TesselPoint *trianglePoints[3]; 2456 2467 TesselPoint *SecondPoint = NULL; 2468 list<BoundaryTriangleSet*> *triangles = NULL; 2457 2469 2458 2470 if (LinesOnBoundary.empty()) { … … 2465 2477 // check whether closest point is "too close" :), then it's inside 2466 2478 if (trianglePoints[0] == NULL) { 2467 *out << Verbose( 1) << "Is the only point, no one else is closeby." << endl;2479 *out << Verbose(2) << "Is the only point, no one else is closeby." << endl; 2468 2480 return NULL; 2469 2481 } 2470 2482 if (trianglePoints[0]->node->DistanceSquared(x) < MYEPSILON) { 2471 *out << Verbose(1) << "Point is right on a tesselation point, no nearest triangle." << endl; 2472 return NULL; 2473 } 2474 list<TesselPoint*> *connectedClosestPoints = GetCircleOfConnectedPoints(out, trianglePoints[0], x); 2475 trianglePoints[1] = connectedClosestPoints->front(); 2476 trianglePoints[2] = connectedClosestPoints->back(); 2477 for (int i=0;i<3;i++) { 2478 if (trianglePoints[i] == NULL) { 2479 *out << Verbose(1) << "IsInnerPoint encounters serious error, point " << i << " not found." << endl; 2480 } 2481 //*out << Verbose(1) << "List of possible points:" << endl; 2482 //*out << Verbose(2) << *trianglePoints[i] << endl; 2483 } 2484 2485 list<BoundaryTriangleSet*> *triangles = FindTriangles(trianglePoints); 2486 2487 delete(connectedClosestPoints); 2483 *out << Verbose(2) << "Point is right on a tesselation point, no nearest triangle." << endl; 2484 PointMap::iterator PointRunner = PointsOnBoundary.find(trianglePoints[0]->nr); 2485 triangles = new list<BoundaryTriangleSet*>; 2486 if (PointRunner != PointsOnBoundary.end()) { 2487 for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++) 2488 for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++) 2489 triangles->push_back(TriangleRunner->second); 2490 triangles->sort(); 2491 triangles->unique(); 2492 } else { 2493 PointRunner = PointsOnBoundary.find(SecondPoint->nr); 2494 trianglePoints[0] = SecondPoint; 2495 if (PointRunner != PointsOnBoundary.end()) { 2496 for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++) 2497 for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++) 2498 triangles->push_back(TriangleRunner->second); 2499 triangles->sort(); 2500 triangles->unique(); 2501 } else { 2502 *out << Verbose(1) << "ERROR: I cannot find a boundary point to the tessel point " << *trianglePoints[0] << "." << endl; 2503 return NULL; 2504 } 2505 } 2506 } else { 2507 list<TesselPoint*> *connectedClosestPoints = GetCircleOfConnectedPoints(out, trianglePoints[0], x); 2508 trianglePoints[1] = connectedClosestPoints->front(); 2509 trianglePoints[2] = connectedClosestPoints->back(); 2510 for (int i=0;i<3;i++) { 2511 if (trianglePoints[i] == NULL) { 2512 *out << Verbose(1) << "ERROR: IsInnerPoint encounters serious error, point " << i << " not found." << endl; 2513 } 2514 *out << Verbose(1) << "List of triangle points:" << endl; 2515 *out << Verbose(2) << *trianglePoints[i] << endl; 2516 } 2517 2518 triangles = FindTriangles(trianglePoints); 2519 *out << Verbose(1) << "List of possible triangles:" << endl; 2520 for(list<BoundaryTriangleSet*>::iterator Runner = triangles->begin(); Runner != triangles->end(); Runner++) 2521 *out << Verbose(2) << **Runner << endl; 2522 2523 delete(connectedClosestPoints); 2524 } 2488 2525 2489 2526 if (triangles->empty()) { 2490 *out << Verbose(0) << "Error: There is no nearest triangle. Please check the tesselation structure."; 2527 *out << Verbose(0) << "ERROR: There is no nearest triangle. Please check the tesselation structure."; 2528 delete(triangles); 2491 2529 return NULL; 2492 2530 } else … … 2504 2542 class BoundaryTriangleSet *result = NULL; 2505 2543 list<BoundaryTriangleSet*> *triangles = FindClosestTrianglesToPoint(out, x, LC); 2544 Vector Center; 2506 2545 2507 2546 if (triangles == NULL) 2508 2547 return NULL; 2509 2548 2510 if (x->ScalarProduct(&triangles->front()->NormalVector) < 0) 2511 result = triangles->back(); 2512 else 2549 if (triangles->size() == 1) { // there is no degenerate case 2513 2550 result = triangles->front(); 2514 2551 *out << Verbose(2) << "Normal Vector of this triangle is " << result->NormalVector << "." << endl; 2552 } else { 2553 result = triangles->front(); 2554 result->GetCenter(&Center); 2555 Center.SubtractVector(x); 2556 *out << Verbose(2) << "Normal Vector of this front side is " << result->NormalVector << "." << endl; 2557 if (Center.ScalarProduct(&result->NormalVector) < 0) { 2558 result = triangles->back(); 2559 *out << Verbose(2) << "Normal Vector of this back side is " << result->NormalVector << "." << endl; 2560 if (Center.ScalarProduct(&result->NormalVector) < 0) { 2561 *out << Verbose(1) << "ERROR: Front and back side yield NormalVector in wrong direction!" << endl; 2562 } 2563 } 2564 } 2515 2565 delete(triangles); 2516 2566 return result; … … 2527 2577 { 2528 2578 class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, &Point, LC); 2529 if (result == NULL) 2579 Vector Center; 2580 2581 if (result == NULL) {// is boundary point or only point in point cloud? 2582 *out << Verbose(1) << Point << " is the only point in vicinity." << endl; 2583 return false; 2584 } 2585 2586 result->GetCenter(&Center); 2587 *out << Verbose(3) << "INFO: Central point of the triangle is " << Center << "." << endl; 2588 Center.SubtractVector(&Point); 2589 *out << Verbose(3) << "INFO: Vector from center to point to test is " << Center << "." << endl; 2590 if (Center.ScalarProduct(&result->NormalVector) > -MYEPSILON) { 2591 *out << Verbose(1) << Point << " is an inner point." << endl; 2530 2592 return true; 2531 if (Point.ScalarProduct(&result->NormalVector) < 0) 2532 return true; 2533 else 2593 } else { 2594 *out << Verbose(1) << Point << " is NOT an inner point." << endl; 2534 2595 return false; 2596 } 2535 2597 } 2536 2598 … … 2544 2606 bool Tesselation::IsInnerPoint(ofstream *out, TesselPoint *Point, LinkedCell* LC) 2545 2607 { 2546 class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, Point->node, LC); 2547 if (result == NULL) 2548 return true; 2549 if (Point->node->ScalarProduct(&result->NormalVector) < 0) 2550 return true; 2551 else 2552 return false; 2608 return IsInnerPoint(out, *(Point->node), LC); 2553 2609 } 2554 2610 … … 2705 2761 } 2706 2762 2707 map <class BoundaryLineSet *, bool> Touched; 2708 map <class BoundaryLineSet *, bool>::iterator line; 2709 for (LineMap::iterator runner = ReferencePoint->lines.begin(); runner != ReferencePoint->lines.end(); runner++) 2710 Touched.insert( pair <class BoundaryLineSet *, bool>(runner->second, false) ); 2763 map <class BoundaryLineSet *, bool> TouchedLine; 2764 map <class BoundaryTriangleSet *, bool> TouchedTriangle; 2765 map <class BoundaryLineSet *, bool>::iterator LineRunner; 2766 map <class BoundaryTriangleSet *, bool>::iterator TriangleRunner; 2767 for (LineMap::iterator Runner = ReferencePoint->lines.begin(); Runner != ReferencePoint->lines.end(); Runner++) { 2768 TouchedLine.insert( pair <class BoundaryLineSet *, bool>(Runner->second, false) ); 2769 for (TriangleMap::iterator Sprinter = Runner->second->triangles.begin(); Sprinter != Runner->second->triangles.end(); Sprinter++) 2770 TouchedTriangle.insert( pair <class BoundaryTriangleSet *, bool>(Sprinter->second, false) ); 2771 } 2711 2772 if (!ReferencePoint->lines.empty()) { 2712 2773 for (LineMap::iterator runner = ReferencePoint->lines.begin(); runner != ReferencePoint->lines.end(); runner++) { 2713 line = Touched.find(runner->second);2714 if ( line == Touched.end()) {2774 LineRunner = TouchedLine.find(runner->second); 2775 if (LineRunner == TouchedLine.end()) { 2715 2776 *out << Verbose(2) << "ERROR: I could not find " << *runner->second << " in the touched list." << endl; 2716 } else if (! line->second) {2717 line->second = true;2777 } else if (!LineRunner->second) { 2778 LineRunner->second = true; 2718 2779 connectedPath = new list<TesselPoint*>; 2719 2780 triangle = NULL; … … 2728 2789 2729 2790 // find next triangle 2730 for (TriangleMap::iterator TriangleRunner = CurrentLine->triangles.begin(); TriangleRunner != CurrentLine->triangles.end(); TriangleRunner++) { 2731 if (TriangleRunner->second != triangle) { // look for first triangle not equal to old one 2732 triangle = TriangleRunner->second; 2733 break; 2791 for (TriangleMap::iterator Runner = CurrentLine->triangles.begin(); Runner != CurrentLine->triangles.end(); Runner++) { 2792 *out << Verbose(3) << "INFO: Inspecting triangle " << *Runner->second << "." << endl; 2793 if ((Runner->second != triangle)) { // look for first triangle not equal to old one 2794 triangle = Runner->second; 2795 TriangleRunner = TouchedTriangle.find(triangle); 2796 if (TriangleRunner != TouchedTriangle.end()) { 2797 if (!TriangleRunner->second) { 2798 TriangleRunner->second = true; 2799 *out << Verbose(3) << "INFO: Connecting triangle is " << *triangle << "." << endl; 2800 break; 2801 } else { 2802 *out << Verbose(3) << "INFO: Skipping " << *triangle << ", as we have already visited it." << endl; 2803 triangle = NULL; 2804 } 2805 } else { 2806 *out << Verbose(2) << "ERROR: I could not find " << *triangle << " in the touched list." << endl; 2807 triangle = NULL; 2808 } 2734 2809 } 2735 2810 } 2811 if (triangle == NULL) 2812 break; 2736 2813 // find next line 2737 2814 for (int i=0;i<3;i++) { 2738 2815 if ((triangle->lines[i] != CurrentLine) && (triangle->lines[i]->ContainsBoundaryPoint(ReferencePoint))) { // not the current line and still containing Point 2739 2816 CurrentLine = triangle->lines[i]; 2740 2817 *out << Verbose(3) << "INFO: Connecting line is " << *CurrentLine << "." << endl; 2741 2818 break; 2742 2819 } 2743 2820 } 2744 line = Touched.find(CurrentLine);2745 if ( line == Touched.end())2821 LineRunner = TouchedLine.find(CurrentLine); 2822 if (LineRunner == TouchedLine.end()) 2746 2823 *out << Verbose(2) << "ERROR: I could not find " << *CurrentLine << " in the touched list." << endl; 2747 2824 else 2748 line->second = true;2825 LineRunner->second = true; 2749 2826 // find next point 2750 2827 CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint); … … 2753 2830 // last point is missing, as it's on start line 2754 2831 *out << Verbose(3) << "INFO: Putting " << *CurrentPoint << " at end of path." << endl; 2755 connectedPath->push_back(StartLine->GetOtherEndpoint(ReferencePoint)->node); 2832 if (StartLine->GetOtherEndpoint(ReferencePoint)->node != connectedPath->back()) 2833 connectedPath->push_back(StartLine->GetOtherEndpoint(ReferencePoint)->node); 2756 2834 2757 2835 ListOfPaths->push_back(connectedPath); … … 2853 2931 2854 2932 /** Removes a boundary point from the envelope while keeping it closed. 2855 * We create new triangles and remove the old ones connected to the point. 2933 * We remove the old triangles connected to the point and re-create new triangles to close the surface following this ansatz: 2934 * -# a closed path(s) of boundary points surrounding the point to be removed is constructed 2935 * -# on each closed path, we pick three adjacent points, create a triangle with them and subtract the middle point from the path 2936 * -# we advance two points (i.e. the next triangle will start at the ending point of the last triangle) and continue as before 2937 * -# the surface is closed, when the path is empty 2938 * Thereby, we (hopefully) make sure that the removed points remains beneath the surface (this is checked via IsInnerPoint eventually). 2856 2939 * \param *out output stream for debugging 2857 2940 * \param *point point to be removed … … 2861 2944 class BoundaryLineSet *line = NULL; 2862 2945 class BoundaryTriangleSet *triangle = NULL; 2863 Vector OldPoint, TetraederVector[3];2946 Vector OldPoint, NormalVector; 2864 2947 double volume = 0; 2865 2948 int count = 0; … … 2887 2970 count+=LineRunner->second->triangles.size(); 2888 2971 map<class BoundaryTriangleSet *, int> Candidates; 2889 for (LineMap::iterator LineRunner = point->lines.begin(); (point != NULL) && (LineRunner != point->lines.end()); LineRunner++) {2972 for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) { 2890 2973 line = LineRunner->second; 2891 2974 for (TriangleMap::iterator TriangleRunner = line->triangles.begin(); TriangleRunner != line->triangles.end(); TriangleRunner++) { … … 2897 2980 // remove all triangles 2898 2981 count=0; 2982 NormalVector.Zero(); 2899 2983 for (map<class BoundaryTriangleSet *, int>::iterator Runner = Candidates.begin(); Runner != Candidates.end(); Runner++) { 2900 2984 *out << Verbose(3) << "INFO: Removing triangle " << *(Runner->first) << "." << endl; 2985 NormalVector.SubtractVector(&Runner->first->NormalVector); // has to point inward 2901 2986 RemoveTesselationTriangle(Runner->first); 2902 2987 count++; … … 2907 2992 list<list<TesselPoint*> *>::iterator ListRunner = ListAdvance; 2908 2993 map<class BoundaryTriangleSet *, int>::iterator NumberRunner = Candidates.begin(); 2994 list<TesselPoint*>::iterator StartNode, MiddleNode, EndNode; 2995 double angle; 2996 double smallestangle; 2997 Vector Point, Reference, OrthogonalVector; 2909 2998 if (count > 2) { // less than three triangles, then nothing will be created 2910 2999 class TesselPoint *TriangleCandidates[3]; … … 2915 3004 2916 3005 connectedPath = *ListRunner; 2917 // initialize the path to start2918 list<TesselPoint*>::iterator CircleRunner = connectedPath->begin();2919 list<TesselPoint*>::iterator OtherCircleRunner = connectedPath->begin();2920 class TesselPoint *CentralNode = *CircleRunner;2921 3006 2922 3007 // re-create all triangles by going through connected points list 2923 // advance two with CircleRunner and one with OtherCircleRunner 2924 CircleRunner++; 2925 CircleRunner++; 2926 OtherCircleRunner++; 2927 cout << Verbose(3) << "INFO: CentralNode is " << *CentralNode << "." << endl; 2928 for (; (OtherCircleRunner != connectedPath->end()) && (CircleRunner != connectedPath->end()); (CircleRunner++), (OtherCircleRunner++)) { 2929 cout << Verbose(4) << "INFO: CircleRunner's node is " << **CircleRunner << "." << endl; 2930 cout << Verbose(4) << "INFO: OtherCircleRunner's node is " << **OtherCircleRunner << "." << endl; 2931 *out << Verbose(3) << "INFO: Creating triangle " << CentralNode->Name << ", " << (*OtherCircleRunner)->Name << " and " << (*CircleRunner)->Name << "." << endl; 3008 list<class BoundaryLineSet *> NewLines; 3009 for (;!connectedPath->empty();) { 3010 // search middle node with widest angle to next neighbours 3011 EndNode = connectedPath->end(); 3012 smallestangle = 0.; 3013 for (MiddleNode = connectedPath->begin(); MiddleNode != connectedPath->end(); MiddleNode++) { 3014 cout << Verbose(3) << "INFO: MiddleNode is " << **MiddleNode << "." << endl; 3015 // construct vectors to next and previous neighbour 3016 StartNode = MiddleNode; 3017 if (StartNode == connectedPath->begin()) 3018 StartNode = connectedPath->end(); 3019 StartNode--; 3020 //cout << Verbose(3) << "INFO: StartNode is " << **StartNode << "." << endl; 3021 Point.CopyVector((*StartNode)->node); 3022 Point.SubtractVector((*MiddleNode)->node); 3023 StartNode = MiddleNode; 3024 StartNode++; 3025 if (StartNode == connectedPath->end()) 3026 StartNode = connectedPath->begin(); 3027 //cout << Verbose(3) << "INFO: EndNode is " << **StartNode << "." << endl; 3028 Reference.CopyVector((*StartNode)->node); 3029 Reference.SubtractVector((*MiddleNode)->node); 3030 OrthogonalVector.CopyVector((*MiddleNode)->node); 3031 OrthogonalVector.SubtractVector(&OldPoint); 3032 OrthogonalVector.MakeNormalVector(&Reference); 3033 angle = GetAngle(Point, Reference, OrthogonalVector); 3034 //if (angle < M_PI) // no wrong-sided triangles, please? 3035 if(fabs(angle - M_PI) < fabs(smallestangle - M_PI)) { // get straightest angle (i.e. construct those triangles with smallest area first) 3036 smallestangle = angle; 3037 EndNode = MiddleNode; 3038 } 3039 } 3040 MiddleNode = EndNode; 3041 if (MiddleNode == connectedPath->end()) { 3042 cout << Verbose(1) << "CRITICAL: Could not find a smallest angle!" << endl; 3043 exit(255); 3044 } 3045 StartNode = MiddleNode; 3046 if (StartNode == connectedPath->begin()) 3047 StartNode = connectedPath->end(); 3048 StartNode--; 3049 EndNode++; 3050 if (EndNode == connectedPath->end()) 3051 EndNode = connectedPath->begin(); 3052 cout << Verbose(4) << "INFO: StartNode is " << **StartNode << "." << endl; 3053 cout << Verbose(4) << "INFO: MiddleNode is " << **MiddleNode << "." << endl; 3054 cout << Verbose(4) << "INFO: EndNode is " << **EndNode << "." << endl; 3055 *out << Verbose(3) << "INFO: Attempting to create triangle " << (*StartNode)->Name << ", " << (*MiddleNode)->Name << " and " << (*EndNode)->Name << "." << endl; 3056 TriangleCandidates[0] = *StartNode; 3057 TriangleCandidates[1] = *MiddleNode; 3058 TriangleCandidates[2] = *EndNode; 3059 triangle = GetPresentTriangle(out, TriangleCandidates); 3060 if (triangle != NULL) { 3061 cout << Verbose(1) << "WARNING: New triangle already present, skipping!" << endl; 3062 StartNode++; 3063 MiddleNode++; 3064 EndNode++; 3065 if (StartNode == connectedPath->end()) 3066 StartNode = connectedPath->begin(); 3067 if (MiddleNode == connectedPath->end()) 3068 MiddleNode = connectedPath->begin(); 3069 if (EndNode == connectedPath->end()) 3070 EndNode = connectedPath->begin(); 3071 continue; 3072 } 2932 3073 *out << Verbose(5) << "Adding new triangle points."<< endl; 2933 TriangleCandidates[0] = CentralNode; 2934 TriangleCandidates[1] = *OtherCircleRunner; 2935 TriangleCandidates[2] = *CircleRunner; 2936 triangle = GetPresentTriangle(out, TriangleCandidates); 2937 AddTesselationPoint(CentralNode, 0); 2938 AddTesselationPoint(*OtherCircleRunner, 1); 2939 AddTesselationPoint(*CircleRunner, 2); 3074 AddTesselationPoint(*StartNode, 0); 3075 AddTesselationPoint(*MiddleNode, 1); 3076 AddTesselationPoint(*EndNode, 2); 2940 3077 *out << Verbose(5) << "Adding new triangle lines."<< endl; 2941 3078 AddTesselationLine(TPS[0], TPS[1], 0); 2942 3079 AddTesselationLine(TPS[0], TPS[2], 1); 3080 NewLines.push_back(BLS[1]); 2943 3081 AddTesselationLine(TPS[1], TPS[2], 2); 2944 3082 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3083 BTS->GetNormalVector(NormalVector); 2945 3084 AddTesselationTriangle(); 2946 3085 // calculate volume summand as a general tetraeder 2947 for (int j=0;j<3;j++) { 2948 TetraederVector[j].CopyVector(TPS[j]->node->node); 2949 TetraederVector[j].SubtractVector(&OldPoint); 3086 volume += CalculateVolumeofGeneralTetraeder(TPS[0]->node->node, TPS[1]->node->node, TPS[2]->node->node, &OldPoint); 3087 // advance number 3088 count++; 3089 3090 // prepare nodes for next triangle 3091 StartNode = EndNode; 3092 cout << Verbose(4) << "Removing " << **MiddleNode << " from closed path, remaining points: " << connectedPath->size() << "." << endl; 3093 connectedPath->remove(*MiddleNode); // remove the middle node (it is surrounded by triangles) 3094 if (connectedPath->size() == 2) { // we are done 3095 connectedPath->remove(*StartNode); // remove the start node 3096 connectedPath->remove(*EndNode); // remove the end node 3097 break; 3098 } else if (connectedPath->size() < 2) { // something's gone wrong! 3099 cout << Verbose(1) << "CRITICAL: There are only two endpoints left!" << endl; 3100 exit(255); 3101 } else { 3102 MiddleNode = StartNode; 3103 MiddleNode++; 3104 if (MiddleNode == connectedPath->end()) 3105 MiddleNode = connectedPath->begin(); 3106 EndNode = MiddleNode; 3107 EndNode++; 3108 if (EndNode == connectedPath->end()) 3109 EndNode = connectedPath->begin(); 2950 3110 } 2951 OldPoint.CopyVector(&TetraederVector[0]);2952 OldPoint.VectorProduct(&TetraederVector[1]);2953 volume += 1./6. * fabs(OldPoint.ScalarProduct(&TetraederVector[2]));2954 // advance number2955 NumberRunner++;2956 count++;2957 if (NumberRunner == Candidates.end())2958 *out << Verbose(2) << "WARN: Maximum of numbers reached!" << endl;2959 3111 } 3112 // maximize the inner lines (we preferentially created lines with a huge angle, which is for the tesselation not wanted though useful for the closing) 3113 if (NewLines.size() > 1) { 3114 list<class BoundaryLineSet *>::iterator Candidate; 3115 class BoundaryLineSet *OtherBase = NULL; 3116 double tmp, maxgain; 3117 do { 3118 maxgain = 0; 3119 for(list<class BoundaryLineSet *>::iterator Runner = NewLines.begin(); Runner != NewLines.end(); Runner++) { 3120 tmp = PickFarthestofTwoBaselines(out, *Runner); 3121 if (maxgain < tmp) { 3122 maxgain = tmp; 3123 Candidate = Runner; 3124 } 3125 } 3126 if (maxgain != 0) { 3127 volume += maxgain; 3128 cout << Verbose(3) << "Flipping baseline with highest volume" << **Candidate << "." << endl; 3129 OtherBase = FlipBaseline(out, *Candidate); 3130 NewLines.erase(Candidate); 3131 NewLines.push_back(OtherBase); 3132 } 3133 } while (maxgain != 0.); 3134 } 3135 2960 3136 ListOfClosedPaths->remove(connectedPath); 2961 3137 delete(connectedPath); … … 2971 3147 *out << Verbose(1) << "No need to create any triangles." << endl; 2972 3148 } 2973 2974 3149 delete(ListOfClosedPaths); 2975 3150 3151 *out << Verbose(1) << "Removed volume is " << volume << "." << endl; 3152 2976 3153 return volume; 2977 3154 }; 2978 3155 2979 3156 2980 2981 /** Checks for a new special triangle whether one of its edges is already present with one one triangle connected.2982 * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not2983 * make it bigger (i.e. closing one (the baseline) and opening two new ones).2984 * \param TPS[3] nodes of the triangle2985 * \return true - there is such a line (i.e. creation of degenerated triangle is valid), false - no such line (don't create)2986 */2987 bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3])2988 {2989 bool result = false;2990 int counter = 0;2991 2992 // check all three points2993 for (int i=0;i<3;i++)2994 for (int j=i+1; j<3; j++) {2995 if (nodes[i]->lines.find(nodes[j]->node->nr) != nodes[i]->lines.end()) { // there already is a line2996 LineMap::iterator FindLine;2997 pair<LineMap::iterator,LineMap::iterator> FindPair;2998 FindPair = nodes[i]->lines.equal_range(nodes[j]->node->nr);2999 for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {3000 // If there is a line with less than two attached triangles, we don't need a new line.3001 if (FindLine->second->triangles.size() < 2) {3002 counter++;3003 break; // increase counter only once per edge3004 }3005 }3006 } else { // no line3007 cout << Verbose(1) << "The line between " << nodes[i] << " and " << nodes[j] << " is not yet present, hence no need for a degenerate triangle." << endl;3008 result = true;3009 }3010 }3011 if (counter > 1) {3012 cout << Verbose(2) << "INFO: Degenerate triangle is ok, at least two, here " << counter << ", existing lines are used." << endl;3013 result = true;3014 }3015 return result;3016 };3017 3018 3019 /** Sort function for the candidate list.3020 */3021 bool SortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2)3022 {3023 Vector BaseLineVector, OrthogonalVector, helper;3024 if (candidate1->BaseLine != candidate2->BaseLine) { // sanity check3025 cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;3026 //return false;3027 exit(1);3028 }3029 // create baseline vector3030 BaseLineVector.CopyVector(candidate1->BaseLine->endpoints[1]->node->node);3031 BaseLineVector.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);3032 BaseLineVector.Normalize();3033 3034 // create normal in-plane vector to cope with acos() non-uniqueness on [0,2pi] (note that is pointing in the "right" direction already, hence ">0" test!)3035 helper.CopyVector(candidate1->BaseLine->endpoints[0]->node->node);3036 helper.SubtractVector(candidate1->point->node);3037 OrthogonalVector.CopyVector(&helper);3038 helper.VectorProduct(&BaseLineVector);3039 OrthogonalVector.SubtractVector(&helper);3040 OrthogonalVector.Normalize();3041 3042 // calculate both angles and correct with in-plane vector3043 helper.CopyVector(candidate1->point->node);3044 helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);3045 double phi = BaseLineVector.Angle(&helper);3046 if (OrthogonalVector.ScalarProduct(&helper) > 0) {3047 phi = 2.*M_PI - phi;3048 }3049 helper.CopyVector(candidate2->point->node);3050 helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);3051 double psi = BaseLineVector.Angle(&helper);3052 if (OrthogonalVector.ScalarProduct(&helper) > 0) {3053 psi = 2.*M_PI - psi;3054 }3055 3056 cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;3057 cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;3058 3059 // return comparison3060 return phi < psi;3061 };3062 3063 /**3064 * Finds the point which is second closest to the provided one.3065 *3066 * @param Point to which to find the second closest other point3067 * @param linked cell structure3068 *3069 * @return point which is second closest to the provided one3070 */3071 TesselPoint* FindSecondClosestPoint(const Vector* Point, LinkedCell* LC)3072 {3073 LinkedNodes *List = NULL;3074 TesselPoint* closestPoint = NULL;3075 TesselPoint* secondClosestPoint = NULL;3076 double distance = 1e16;3077 double secondDistance = 1e16;3078 Vector helper;3079 int N[NDIM], Nlower[NDIM], Nupper[NDIM];3080 3081 LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly3082 for(int i=0;i<NDIM;i++) // store indices of this cell3083 N[i] = LC->n[i];3084 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;3085 3086 LC->GetNeighbourBounds(Nlower, Nupper);3087 //cout << endl;3088 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)3089 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)3090 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {3091 List = LC->GetCurrentCell();3092 cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;3093 if (List != NULL) {3094 for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {3095 helper.CopyVector(Point);3096 helper.SubtractVector((*Runner)->node);3097 double currentNorm = helper. Norm();3098 if (currentNorm < distance) {3099 // remember second point3100 secondDistance = distance;3101 secondClosestPoint = closestPoint;3102 // mark down new closest point3103 distance = currentNorm;3104 closestPoint = (*Runner);3105 cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;3106 }3107 }3108 } else {3109 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","3110 << LC->n[2] << " is invalid!" << endl;3111 }3112 }3113 3114 return secondClosestPoint;3115 };3116 3117 /**3118 * Finds the point which is closest to the provided one.3119 *3120 * @param Point to which to find the closest other point3121 * @param SecondPoint the second closest other point on return, NULL if none found3122 * @param linked cell structure3123 *3124 * @return point which is closest to the provided one, NULL if none found3125 */3126 TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC)3127 {3128 LinkedNodes *List = NULL;3129 TesselPoint* closestPoint = NULL;3130 SecondPoint = NULL;3131 double distance = 1e16;3132 double secondDistance = 1e16;3133 Vector helper;3134 int N[NDIM], Nlower[NDIM], Nupper[NDIM];3135 3136 LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly3137 for(int i=0;i<NDIM;i++) // store indices of this cell3138 N[i] = LC->n[i];3139 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;3140 3141 LC->GetNeighbourBounds(Nlower, Nupper);3142 //cout << endl;3143 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)3144 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)3145 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {3146 List = LC->GetCurrentCell();3147 cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;3148 if (List != NULL) {3149 for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {3150 helper.CopyVector(Point);3151 helper.SubtractVector((*Runner)->node);3152 double currentNorm = helper. Norm();3153 if (currentNorm < distance) {3154 secondDistance = distance;3155 SecondPoint = closestPoint;3156 distance = currentNorm;3157 closestPoint = (*Runner);3158 cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;3159 } else if (currentNorm < secondDistance) {3160 secondDistance = currentNorm;3161 SecondPoint = (*Runner);3162 cout << Verbose(2) << "INFO: New Second Nearest Neighbour is " << *SecondPoint << "." << endl;3163 }3164 }3165 } else {3166 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","3167 << LC->n[2] << " is invalid!" << endl;3168 }3169 }3170 3171 return closestPoint;3172 };3173 3157 3174 3158 /** … … 3207 3191 FindTriangle = FindLine->second->triangles.begin(); 3208 3192 for (; FindTriangle != FindLine->second->triangles.end(); FindTriangle++) { 3209 if (( 3210 (FindTriangle->second->endpoints[0] == TrianglePoints[0]) 3211 || (FindTriangle->second->endpoints[0] == TrianglePoints[1]) 3212 || (FindTriangle->second->endpoints[0] == TrianglePoints[2]) 3213 ) && ( 3214 (FindTriangle->second->endpoints[1] == TrianglePoints[0]) 3215 || (FindTriangle->second->endpoints[1] == TrianglePoints[1]) 3216 || (FindTriangle->second->endpoints[1] == TrianglePoints[2]) 3217 ) && ( 3218 (FindTriangle->second->endpoints[2] == TrianglePoints[0]) 3219 || (FindTriangle->second->endpoints[2] == TrianglePoints[1]) 3220 || (FindTriangle->second->endpoints[2] == TrianglePoints[2]) 3221 ) 3222 ) { 3193 if (FindTriangle->second->IsPresentTupel(TrianglePoints)) { 3223 3194 result->push_back(FindTriangle->second); 3224 3195 } … … 3238 3209 3239 3210 /** 3211 * Finds all degenerated lines within the tesselation structure. 3212 * 3213 * @return map of keys of degenerated line pairs, each line occurs twice 3214 * in the list, once as key and once as value 3215 */ 3216 map<int, int> * Tesselation::FindAllDegeneratedLines() 3217 { 3218 map<int, class BoundaryLineSet *> AllLines; 3219 map<int, int> * DegeneratedLines = new map<int, int>; 3220 3221 // sanity check 3222 if (LinesOnBoundary.empty()) { 3223 cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure."; 3224 return DegeneratedLines; 3225 } 3226 3227 LineMap::iterator LineRunner1; 3228 pair<LineMap::iterator, bool> tester; 3229 for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) { 3230 tester = AllLines.insert( pair<int,BoundaryLineSet *> (LineRunner1->second->endpoints[0]->Nr, LineRunner1->second) ); 3231 if ((!tester.second) && (tester.first->second->endpoints[1]->Nr == LineRunner1->second->endpoints[1]->Nr)) { // found degenerated line 3232 DegeneratedLines->insert ( pair<int, int> (LineRunner1->second->Nr, tester.first->second->Nr) ); 3233 DegeneratedLines->insert ( pair<int, int> (tester.first->second->Nr, LineRunner1->second->Nr) ); 3234 } 3235 } 3236 3237 AllLines.clear(); 3238 3239 cout << Verbose(1) << "FindAllDegeneratedLines() found " << DegeneratedLines->size() << " lines." << endl; 3240 map<int,int>::iterator it; 3241 for (it = DegeneratedLines->begin(); it != DegeneratedLines->end(); it++) 3242 cout << Verbose(2) << (*it).first << " => " << (*it).second << endl; 3243 3244 return DegeneratedLines; 3245 } 3246 3247 /** 3240 3248 * Finds all degenerated triangles within the tesselation structure. 3241 3249 * … … 3243 3251 * in the list, once as key and once as value 3244 3252 */ 3245 map<int, int> Tesselation::FindAllDegeneratedTriangles() 3246 { 3247 map<int, int> DegeneratedTriangles; 3248 3249 // sanity check 3250 if (LinesOnBoundary.empty()) { 3251 cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure."; 3252 return DegeneratedTriangles; 3253 } 3254 3255 LineMap::iterator LineRunner1, LineRunner2; 3256 3257 for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) { 3258 for (LineRunner2 = LinesOnBoundary.begin(); LineRunner2 != LinesOnBoundary.end(); ++LineRunner2) { 3259 if ((LineRunner1->second != LineRunner2->second) 3260 && (LineRunner1->second->endpoints[0] == LineRunner2->second->endpoints[0]) 3261 && (LineRunner1->second->endpoints[1] == LineRunner2->second->endpoints[1]) 3262 ) { 3263 TriangleMap::iterator TriangleRunner1 = LineRunner1->second->triangles.begin(), 3264 TriangleRunner2 = LineRunner2->second->triangles.begin(); 3265 3266 for (; TriangleRunner1 != LineRunner1->second->triangles.end(); ++TriangleRunner1) { 3267 for (; TriangleRunner2 != LineRunner2->second->triangles.end(); ++TriangleRunner2) { 3268 if ((TriangleRunner1->second != TriangleRunner2->second) 3269 && (TriangleRunner1->second->endpoints[0] == TriangleRunner2->second->endpoints[0]) 3270 && (TriangleRunner1->second->endpoints[1] == TriangleRunner2->second->endpoints[1]) 3271 && (TriangleRunner1->second->endpoints[2] == TriangleRunner2->second->endpoints[2]) 3272 ) { 3273 DegeneratedTriangles[TriangleRunner1->second->Nr] = TriangleRunner2->second->Nr; 3274 DegeneratedTriangles[TriangleRunner2->second->Nr] = TriangleRunner1->second->Nr; 3275 } 3276 } 3253 map<int, int> * Tesselation::FindAllDegeneratedTriangles() 3254 { 3255 map<int, int> * DegeneratedLines = FindAllDegeneratedLines(); 3256 map<int, int> * DegeneratedTriangles = new map<int, int>; 3257 3258 TriangleMap::iterator TriangleRunner1, TriangleRunner2; 3259 LineMap::iterator Liner; 3260 class BoundaryLineSet *line1 = NULL, *line2 = NULL; 3261 3262 for (map<int, int>::iterator LineRunner = DegeneratedLines->begin(); LineRunner != DegeneratedLines->end(); ++LineRunner) { 3263 // run over both lines' triangles 3264 Liner = LinesOnBoundary.find(LineRunner->first); 3265 if (Liner != LinesOnBoundary.end()) 3266 line1 = Liner->second; 3267 Liner = LinesOnBoundary.find(LineRunner->second); 3268 if (Liner != LinesOnBoundary.end()) 3269 line2 = Liner->second; 3270 for (TriangleRunner1 = line1->triangles.begin(); TriangleRunner1 != line1->triangles.end(); ++TriangleRunner1) { 3271 for (TriangleRunner2 = line2->triangles.begin(); TriangleRunner2 != line2->triangles.end(); ++TriangleRunner2) { 3272 if ((TriangleRunner1->second != TriangleRunner2->second) 3273 && (TriangleRunner1->second->IsPresentTupel(TriangleRunner2->second))) { 3274 DegeneratedTriangles->insert( pair<int, int> (TriangleRunner1->second->Nr, TriangleRunner2->second->Nr) ); 3275 DegeneratedTriangles->insert( pair<int, int> (TriangleRunner2->second->Nr, TriangleRunner1->second->Nr) ); 3277 3276 } 3278 3277 } 3279 3278 } 3280 3279 } 3281 3282 cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles.size() << " triangles." << endl; 3280 delete(DegeneratedLines); 3281 3282 cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles->size() << " triangles:" << endl; 3283 3283 map<int,int>::iterator it; 3284 for (it = DegeneratedTriangles .begin(); it != DegeneratedTriangles.end(); it++)3284 for (it = DegeneratedTriangles->begin(); it != DegeneratedTriangles->end(); it++) 3285 3285 cout << Verbose(2) << (*it).first << " => " << (*it).second << endl; 3286 3286 … … 3294 3294 void Tesselation::RemoveDegeneratedTriangles() 3295 3295 { 3296 map<int, int> DegeneratedTriangles = FindAllDegeneratedTriangles(); 3297 3298 for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles.begin(); 3299 TriangleKeyRunner != DegeneratedTriangles.end(); ++TriangleKeyRunner 3296 map<int, int> * DegeneratedTriangles = FindAllDegeneratedTriangles(); 3297 TriangleMap::iterator finder; 3298 BoundaryTriangleSet *triangle = NULL, *partnerTriangle = NULL; 3299 int count = 0; 3300 3301 for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles->begin(); 3302 TriangleKeyRunner != DegeneratedTriangles->end(); ++TriangleKeyRunner 3300 3303 ) { 3301 BoundaryTriangleSet *triangle = TrianglesOnBoundary.find(TriangleKeyRunner->first)->second, 3302 *partnerTriangle = TrianglesOnBoundary.find(TriangleKeyRunner->second)->second; 3304 finder = TrianglesOnBoundary.find(TriangleKeyRunner->first); 3305 if (finder != TrianglesOnBoundary.end()) 3306 triangle = finder->second; 3307 else 3308 break; 3309 finder = TrianglesOnBoundary.find(TriangleKeyRunner->second); 3310 if (finder != TrianglesOnBoundary.end()) 3311 partnerTriangle = finder->second; 3312 else 3313 break; 3303 3314 3304 3315 bool trianglesShareLine = false; … … 3312 3323 && (triangle->endpoints[0]->LinesCount > 2) 3313 3324 ) { 3325 // check whether we have to fix lines 3326 BoundaryTriangleSet *Othertriangle = NULL; 3327 BoundaryTriangleSet *OtherpartnerTriangle = NULL; 3328 TriangleMap::iterator TriangleRunner; 3329 for (int i = 0; i < 3; ++i) 3330 for (int j = 0; j < 3; ++j) 3331 if (triangle->lines[i] != partnerTriangle->lines[j]) { 3332 // get the other two triangles 3333 for (TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); ++TriangleRunner) 3334 if (TriangleRunner->second != triangle) { 3335 Othertriangle = TriangleRunner->second; 3336 } 3337 for (TriangleRunner = partnerTriangle->lines[i]->triangles.begin(); TriangleRunner != partnerTriangle->lines[i]->triangles.end(); ++TriangleRunner) 3338 if (TriangleRunner->second != partnerTriangle) { 3339 OtherpartnerTriangle = TriangleRunner->second; 3340 } 3341 /// interchanges their lines so that triangle->lines[i] == partnerTriangle->lines[j] 3342 // the line of triangle receives the degenerated ones 3343 triangle->lines[i]->triangles.erase(Othertriangle->Nr); 3344 triangle->lines[i]->triangles.insert( TrianglePair( partnerTriangle->Nr, partnerTriangle) ); 3345 for (int k=0;k<3;k++) 3346 if (triangle->lines[i] == Othertriangle->lines[k]) { 3347 Othertriangle->lines[k] = partnerTriangle->lines[j]; 3348 break; 3349 } 3350 // the line of partnerTriangle receives the non-degenerated ones 3351 partnerTriangle->lines[j]->triangles.erase( partnerTriangle->Nr); 3352 partnerTriangle->lines[j]->triangles.insert( TrianglePair( Othertriangle->Nr, Othertriangle) ); 3353 partnerTriangle->lines[j] = triangle->lines[i]; 3354 } 3355 3356 // erase the pair 3357 count += (int) DegeneratedTriangles->erase(triangle->Nr); 3314 3358 cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *triangle << "." << endl; 3315 3359 RemoveTesselationTriangle(triangle); 3360 count += (int) DegeneratedTriangles->erase(partnerTriangle->Nr); 3316 3361 cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *partnerTriangle << "." << endl; 3317 3362 RemoveTesselationTriangle(partnerTriangle); 3318 DegeneratedTriangles.erase(DegeneratedTriangles.find(partnerTriangle->Nr));3319 3363 } else { 3320 3364 cout << Verbose(1) << "RemoveDegeneratedTriangles() does not remove triangle " << *triangle … … 3323 3367 } 3324 3368 } 3369 delete(DegeneratedTriangles); 3370 3371 cout << Verbose(1) << "RemoveDegeneratedTriangles() removed " << count << " triangles:" << endl; 3325 3372 } 3326 3373 3327 /** Gets the angle between a point and a reference relative to the provided center. 3328 * We have two shanks point and reference between which the angle is calculated 3329 * and by scalar product with OrthogonalVector we decide the interval. 3330 * @param point to calculate the angle for 3331 * @param reference to which to calculate the angle 3332 * @param OrthogonalVector points in direction of [pi,2pi] interval 3333 * 3334 * @return angle between point and reference 3335 */ 3336 double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector) 3337 { 3338 if (reference.IsZero()) 3339 return M_PI; 3340 3341 // calculate both angles and correct with in-plane vector 3342 if (point.IsZero()) 3343 return M_PI; 3344 double phi = point.Angle(&reference); 3345 if (OrthogonalVector.ScalarProduct(&point) > 0) { 3346 phi = 2.*M_PI - phi; 3347 } 3348 3349 cout << Verbose(4) << "INFO: " << point << " has angle " << phi << " with respect to reference " << reference << "." << endl; 3350 3351 return phi; 3352 } 3353 3374 /** Adds an outside Tesselpoint to the envelope via (two) degenerated triangles. 3375 * We look for the closest point on the boundary, we look through its connected boundary lines and 3376 * seek the one with the minimum angle between its center point and the new point and this base line. 3377 * We open up the line by adding a degenerated triangle, whose other side closes the base line again. 3378 * \param *out output stream for debugging 3379 * \param *point point to add 3380 * \param *LC Linked Cell structure to find nearest point 3381 */ 3382 void Tesselation::AddBoundaryPointByDegeneratedTriangle(ofstream *out, class TesselPoint *point, LinkedCell *LC) 3383 { 3384 *out << Verbose(2) << "Begin of AddBoundaryPointByDegeneratedTriangle" << endl; 3385 3386 // find nearest boundary point 3387 class TesselPoint *BackupPoint = NULL; 3388 class TesselPoint *NearestPoint = FindClosestPoint(point->node, BackupPoint, LC); 3389 class BoundaryPointSet *NearestBoundaryPoint = NULL; 3390 PointMap::iterator PointRunner; 3391 3392 if (NearestPoint == point) 3393 NearestPoint = BackupPoint; 3394 PointRunner = PointsOnBoundary.find(NearestPoint->nr); 3395 if (PointRunner != PointsOnBoundary.end()) { 3396 NearestBoundaryPoint = PointRunner->second; 3397 } else { 3398 *out << Verbose(1) << "ERROR: I cannot find the boundary point." << endl; 3399 return; 3400 } 3401 *out << Verbose(2) << "Nearest point on boundary is " << NearestPoint->Name << "." << endl; 3402 3403 // go through its lines and find the best one to split 3404 Vector CenterToPoint; 3405 Vector BaseLine; 3406 double angle, BestAngle = 0.; 3407 class BoundaryLineSet *BestLine = NULL; 3408 for (LineMap::iterator Runner = NearestBoundaryPoint->lines.begin(); Runner != NearestBoundaryPoint->lines.end(); Runner++) { 3409 BaseLine.CopyVector(Runner->second->endpoints[0]->node->node); 3410 BaseLine.SubtractVector(Runner->second->endpoints[1]->node->node); 3411 CenterToPoint.CopyVector(Runner->second->endpoints[0]->node->node); 3412 CenterToPoint.AddVector(Runner->second->endpoints[1]->node->node); 3413 CenterToPoint.Scale(0.5); 3414 CenterToPoint.SubtractVector(point->node); 3415 angle = CenterToPoint.Angle(&BaseLine); 3416 if (fabs(angle - M_PI/2.) < fabs(BestAngle - M_PI/2.)) { 3417 BestAngle = angle; 3418 BestLine = Runner->second; 3419 } 3420 } 3421 3422 // remove one triangle from the chosen line 3423 class BoundaryTriangleSet *TempTriangle = (BestLine->triangles.begin())->second; 3424 BestLine->triangles.erase(TempTriangle->Nr); 3425 int nr = -1; 3426 for (int i=0;i<3; i++) { 3427 if (TempTriangle->lines[i] == BestLine) { 3428 nr = i; 3429 break; 3430 } 3431 } 3432 3433 // create new triangle to connect point (connects automatically with the missing spot of the chosen line) 3434 *out << Verbose(5) << "Adding new triangle points."<< endl; 3435 AddTesselationPoint((BestLine->endpoints[0]->node), 0); 3436 AddTesselationPoint((BestLine->endpoints[1]->node), 1); 3437 AddTesselationPoint(point, 2); 3438 *out << Verbose(5) << "Adding new triangle lines."<< endl; 3439 AddTesselationLine(TPS[0], TPS[1], 0); 3440 AddTesselationLine(TPS[0], TPS[2], 1); 3441 AddTesselationLine(TPS[1], TPS[2], 2); 3442 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3443 BTS->GetNormalVector(TempTriangle->NormalVector); 3444 BTS->NormalVector.Scale(-1.); 3445 *out << Verbose(3) << "INFO: NormalVector of new triangle is " << BTS->NormalVector << "." << endl; 3446 AddTesselationTriangle(); 3447 3448 // create other side of this triangle and close both new sides of the first created triangle 3449 *out << Verbose(5) << "Adding new triangle points."<< endl; 3450 AddTesselationPoint((BestLine->endpoints[0]->node), 0); 3451 AddTesselationPoint((BestLine->endpoints[1]->node), 1); 3452 AddTesselationPoint(point, 2); 3453 *out << Verbose(5) << "Adding new triangle lines."<< endl; 3454 AddTesselationLine(TPS[0], TPS[1], 0); 3455 AddTesselationLine(TPS[0], TPS[2], 1); 3456 AddTesselationLine(TPS[1], TPS[2], 2); 3457 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3458 BTS->GetNormalVector(TempTriangle->NormalVector); 3459 *out << Verbose(3) << "INFO: NormalVector of other new triangle is " << BTS->NormalVector << "." << endl; 3460 AddTesselationTriangle(); 3461 3462 // add removed triangle to the last open line of the second triangle 3463 for (int i=0;i<3;i++) { // look for the same line as BestLine (only it's its degenerated companion) 3464 if ((BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[0])) && (BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[1]))) { 3465 if (BestLine == BTS->lines[i]){ 3466 *out << Verbose(1) << "CRITICAL: BestLine is same as found line, something's wrong here!" << endl; 3467 exit(255); 3468 } 3469 BTS->lines[i]->triangles.insert( pair<int, class BoundaryTriangleSet *> (TempTriangle->Nr, TempTriangle) ); 3470 TempTriangle->lines[nr] = BTS->lines[i]; 3471 break; 3472 } 3473 } 3474 3475 // exit 3476 *out << Verbose(2) << "End of AddBoundaryPointByDegeneratedTriangle" << endl; 3477 }; 3478 3479 /** Writes the envelope to file. 3480 * \param *out otuput stream for debugging 3481 * \param *filename basename of output file 3482 * \param *cloud PointCloud structure with all nodes 3483 */ 3484 void Tesselation::Output(ofstream *out, const char *filename, PointCloud *cloud) 3485 { 3486 ofstream *tempstream = NULL; 3487 string NameofTempFile; 3488 char NumberName[255]; 3489 3490 if (LastTriangle != NULL) { 3491 sprintf(NumberName, "-%04d-%s_%s_%s", (int)TrianglesOnBoundary.size(), LastTriangle->endpoints[0]->node->Name, LastTriangle->endpoints[1]->node->Name, LastTriangle->endpoints[2]->node->Name); 3492 if (DoTecplotOutput) { 3493 string NameofTempFile(filename); 3494 NameofTempFile.append(NumberName); 3495 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 3496 NameofTempFile.erase(npos, 1); 3497 NameofTempFile.append(TecplotSuffix); 3498 *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 3499 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 3500 WriteTecplotFile(out, tempstream, this, cloud, TriangleFilesWritten); 3501 tempstream->close(); 3502 tempstream->flush(); 3503 delete(tempstream); 3504 } 3505 3506 if (DoRaster3DOutput) { 3507 string NameofTempFile(filename); 3508 NameofTempFile.append(NumberName); 3509 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 3510 NameofTempFile.erase(npos, 1); 3511 NameofTempFile.append(Raster3DSuffix); 3512 *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 3513 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 3514 WriteRaster3dFile(out, tempstream, this, cloud); 3515 IncludeSphereinRaster3D(out, tempstream, this, cloud); 3516 tempstream->close(); 3517 tempstream->flush(); 3518 delete(tempstream); 3519 } 3520 } 3521 if (DoTecplotOutput || DoRaster3DOutput) 3522 TriangleFilesWritten++; 3523 };
Note:
See TracChangeset
for help on using the changeset viewer.
