Changes in src/tesselation.cpp [f66195:29812d]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/tesselation.cpp
rf66195 r29812d 6 6 */ 7 7 8 #include <fstream>9 10 #include "linkedcell.hpp"11 8 #include "tesselation.hpp" 12 #include "tesselationhelpers.hpp" 13 #include "vector.hpp" 14 #include "verbose.hpp" 15 16 class molecule; 9 #include "memoryallocator.hpp" 17 10 18 11 // ======================================== Points on Boundary ================================= … … 44 37 BoundaryPointSet::~BoundaryPointSet() 45 38 { 46 //cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;39 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 47 40 if (!lines.empty()) 48 41 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl; … … 74 67 ostream & operator <<(ostream &ost, BoundaryPointSet &a) 75 68 { 76 ost << "[" << a.Nr << "|" << a.node->Name << " at " << *a.node->node << "]";69 ost << "[" << a.Nr << "|" << a.node->Name << "]"; 77 70 return ost; 78 71 } … … 132 125 for (LineMap::iterator Runner = erasor.first; Runner != erasor.second; Runner++) 133 126 if ((*Runner).second == this) { 134 //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;127 cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 135 128 endpoints[i]->lines.erase(Runner); 136 129 break; 137 130 } 138 131 } else { // there's just a single line left 139 if (endpoints[i]->lines.erase(Nr)) { 140 //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 141 } 132 if (endpoints[i]->lines.erase(Nr)) 133 cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 142 134 } 143 135 if (endpoints[i]->lines.empty()) { 144 //cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;136 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 145 137 if (endpoints[i] != NULL) { 146 138 delete(endpoints[i]); … … 176 168 177 169 /** Checks whether the adjacent triangles of a baseline are convex or not. 178 * We sum the two angles of each height vector with respect to the center of the baseline.170 * We sum the two angles of each normal vector with a ficticious normnal vector from this baselinbe pointing outwards. 179 171 * If greater/equal M_PI than we are convex. 180 172 * \param *out output stream for debugging … … 186 178 // get the two triangles 187 179 if (triangles.size() != 2) { 188 *out << Verbose(1) << "ERROR: Baseline " << *this << " is connect edto less than two triangles, Tesselation incomplete!" << endl;180 *out << Verbose(1) << "ERROR: Baseline " << *this << " is connect to less than two triangles, Tesselation incomplete!" << endl; 189 181 return true; 190 182 } … … 209 201 NormalCheck.Scale(sign); 210 202 sign = -sign; 211 if (runner->second->NormalVector.NormSquared() > MYEPSILON) 212 BaseLineNormal.CopyVector(&runner->second->NormalVector); // yes, copy second on top of first 213 else { 214 *out << Verbose(1) << "CRITICAL: Triangle " << *runner->second << " has zero normal vector!" << endl; 215 exit(255); 216 } 203 BaseLineNormal.SubtractVector(&runner->second->NormalVector); // we subtract as BaseLineNormal has to point inward in direction of [pi,2pi] 217 204 node = runner->second->GetThirdEndpoint(this); 218 205 if (node != NULL) { … … 224 211 i++; 225 212 } else { 226 //*out << Verbose(2) << " ERROR: I cannot find third node in triangle, something's wrong." << endl;213 //*out << Verbose(2) << "WARNING: I cannot find third node in triangle, something's wrong." << endl; 227 214 return true; 228 215 } … … 230 217 //*out << Verbose(3) << "INFO: BaselineNormal is " << BaseLineNormal << "." << endl; 231 218 if (NormalCheck.NormSquared() < MYEPSILON) { 232 *out << Verbose( 3) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl;219 *out << Verbose(2) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl; 233 220 return true; 234 221 } 235 BaseLineNormal.Scale(-1.);236 222 double angle = GetAngle(helper[0], helper[1], BaseLineNormal); 237 223 if ((angle - M_PI) > -MYEPSILON) { 238 *out << Verbose( 3) << "ACCEPT: Angle is greater than pi: convex." << endl;224 *out << Verbose(2) << "ACCEPT: Angle is greater than pi: convex." << endl; 239 225 return true; 240 226 } else { 241 *out << Verbose( 3) << "REJECT: Angle is less than pi: concave." << endl;227 *out << Verbose(2) << "REJECT: Angle is less than pi: concave." << endl; 242 228 return false; 243 229 } … … 276 262 ostream & operator <<(ostream &ost, BoundaryLineSet &a) 277 263 { 278 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 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]"; 279 265 return ost; 280 266 }; … … 346 332 for (int i = 0; i < 3; i++) { 347 333 if (lines[i] != NULL) { 348 if (lines[i]->triangles.erase(Nr)) { 349 //cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl; 350 } 334 if (lines[i]->triangles.erase(Nr)) 335 cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl; 351 336 if (lines[i]->triangles.empty()) { 352 //cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;337 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 353 338 delete (lines[i]); 354 339 lines[i] = NULL; … … 356 341 } 357 342 } 358 //cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl;343 cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl; 359 344 }; 360 345 … … 376 361 * We call Vector::GetIntersectionWithPlane() to receive the intersection point with the plane 377 362 * This we test if it's really on the plane and whether it's inside the triangle on the plane or not. 378 * The latter is done as follows: We calculate the cross point of one of the triangle's baseline with the line379 * given by the intersection and the third basepoint. Then, we check whether it's on the baseline (i.e. between380 * the first two basepoints) or not.363 * The latter is done as follows: if it's really outside, then for any endpoint of the triangle and it's opposite 364 * base line, the intersection between the line from endpoint to intersection and the base line will have a Vector::NormSquared() 365 * smaller than the first line. 381 366 * \param *out output stream for debugging 382 367 * \param *MolCenter offset vector of line … … 410 395 exit(255); 411 396 } 412 CrossPoint.SubtractVector(endpoints[i%3]->node->node); // cross point was returned as absolute vector397 CrossPoint.SubtractVector(endpoints[i%3]->node->node); 413 398 414 399 // check whether intersection is inside or not by comparing length of intersection and length of cross point 415 if ((CrossPoint.NormSquared() - helper.NormSquared()) <MYEPSILON) { // inside400 if ((CrossPoint.NormSquared() - helper.NormSquared()) > -MYEPSILON) { // inside 416 401 return true; 417 402 } else { // outside! … … 441 426 for(int i=0;i<3;i++) 442 427 if (point == endpoints[i]) 443 return true;444 return false;445 };446 447 /** Checks whether point is any of the three endpoints this triangle contains.448 * \param *point TesselPoint to test449 * \return true - point is of the triangle, false - is not450 */451 bool BoundaryTriangleSet::ContainsBoundaryPoint(class TesselPoint *point)452 {453 for(int i=0;i<3;i++)454 if (point == endpoints[i]->node)455 428 return true; 456 429 return false; … … 478 451 }; 479 452 480 /** Checks whether three given \a *Points coincide with triangle's endpoints.481 * \param *Points[3] pointer to BoundaryPointSet482 * \return true - is the very triangle, false - is not483 */484 bool BoundaryTriangleSet::IsPresentTupel(class BoundaryTriangleSet *T)485 {486 return (((endpoints[0] == T->endpoints[0])487 || (endpoints[0] == T->endpoints[1])488 || (endpoints[0] == T->endpoints[2])489 ) && (490 (endpoints[1] == T->endpoints[0])491 || (endpoints[1] == T->endpoints[1])492 || (endpoints[1] == T->endpoints[2])493 ) && (494 (endpoints[2] == T->endpoints[0])495 || (endpoints[2] == T->endpoints[1])496 || (endpoints[2] == T->endpoints[2])497 498 ));499 };500 501 453 /** Returns the endpoint which is not contained in the given \a *line. 502 454 * \param *line baseline defining two endpoints … … 533 485 ostream &operator <<(ostream &ost, BoundaryTriangleSet &a) 534 486 { 535 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " at " << *a.endpoints[0]->node->node << ","536 << a.endpoints[1]->node->Name << " at " << *a.endpoints[1]->node->node << "," << a.endpoints[2]->node->Name << " at " << *a.endpoints[2]->node->node << "]";487 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 488 << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 537 489 return ost; 538 490 }; … … 553 505 TesselPoint::~TesselPoint() 554 506 { 507 Free(&Name); 555 508 }; 556 509 … … 559 512 ostream & operator << (ostream &ost, const TesselPoint &a) 560 513 { 561 ost << "[" << (a.Name) << "|" << a.Name << " at " << *a.node<< "]";514 ost << "[" << (a.Name) << "|" << &a << "]"; 562 515 return ost; 563 516 }; … … 616 569 TrianglesOnBoundaryCount = 0; 617 570 InternalPointer = PointsOnBoundary.begin(); 618 LastTriangle = NULL;619 TriangleFilesWritten = 0;620 571 } 621 572 ; … … 634 585 cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl; 635 586 } 636 cout << "This envelope was written to file " << TriangleFilesWritten << " times(s)." << endl;637 587 } 638 588 ; … … 1102 1052 Vector *Center = cloud->GetCenter(out); 1103 1053 list<BoundaryTriangleSet*> *triangles = NULL; 1104 bool AddFlag = false;1105 LinkedCell *BoundaryPoints = NULL;1106 1054 1107 1055 *out << Verbose(1) << "Begin of InsertStraddlingPoints" << endl; 1108 1056 1109 1057 cloud->GoToFirst(); 1110 BoundaryPoints = new LinkedCell(this, 5.);1111 1058 while (!cloud->IsEnd()) { // we only have to go once through all points, as boundary can become only bigger 1112 if (AddFlag) { 1113 delete(BoundaryPoints); 1114 BoundaryPoints = new LinkedCell(this, 5.); 1115 AddFlag = false; 1116 } 1059 LinkedCell BoundaryPoints(this, 5.); 1117 1060 Walker = cloud->GetPoint(); 1118 1061 *out << Verbose(2) << "Current point is " << *Walker << "." << endl; 1119 1062 // get the next triangle 1120 triangles = FindClosestTrianglesToPoint(out, Walker->node, BoundaryPoints); 1121 BTS = triangles->front(); 1122 if ((triangles == NULL) || (BTS->ContainsBoundaryPoint(Walker))) { 1123 *out << Verbose(2) << "No triangles found, probably a tesselation point itself." << endl; 1063 triangles = FindClosestTrianglesToPoint(out, Walker->node, &BoundaryPoints); 1064 if (triangles == NULL) { 1065 *out << Verbose(1) << "No triangles found, probably a tesselation point itself." << endl; 1124 1066 cloud->GoToNext(); 1125 1067 continue; 1126 1068 } else { 1069 BTS = triangles->front(); 1127 1070 } 1128 1071 *out << Verbose(2) << "Closest triangle is " << *BTS << "." << endl; … … 1147 1090 // add Walker to boundary points 1148 1091 *out << Verbose(2) << "Adding " << *Walker << " to BoundaryPoints." << endl; 1149 AddFlag = true;1150 1092 if (AddBoundaryPoint(Walker,0)) 1151 1093 NewPoint = BPS[0]; … … 1238 1180 } else { 1239 1181 delete TPS[n]; 1240 cout << Verbose( 4) << "Node " << *((InsertUnique.first)->second->node) << " is already present in PointsOnBoundary." << endl;1182 cout << Verbose(3) << "Node " << *((InsertUnique.first)->second->node) << " is already present in PointsOnBoundary." << endl; 1241 1183 TPS[n] = (InsertUnique.first)->second; 1242 1184 } … … 1255 1197 1256 1198 if (a->lines.find(b->node->nr) != a->lines.end()) { 1257 LineMap::iterator FindLine = a->lines.find(b->node->nr);1199 LineMap::iterator FindLine; 1258 1200 pair<LineMap::iterator,LineMap::iterator> FindPair; 1259 1201 FindPair = a->lines.equal_range(b->node->nr); 1260 cout << Verbose(5) << "INFO: There is at least one line between " << *a << " and " << *b << ": " << *(FindLine->second) << "." << endl; 1261 1262 for (FindLine = FindPair.first; FindLine != FindPair.second; FindLine++) { 1202 1203 for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) { 1263 1204 // If there is a line with less than two attached triangles, we don't need a new line. 1264 1205 if (FindLine->second->triangles.size() < 2) { 1265 1206 insertNewLine = false; 1266 cout << Verbose( 4) << "Using existing line " << *FindLine->second << endl;1207 cout << Verbose(3) << "Using existing line " << *FindLine->second << endl; 1267 1208 1268 1209 BPS[0] = FindLine->second->endpoints[0]; … … 1291 1232 void Tesselation::AlwaysAddTesselationTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n) 1292 1233 { 1293 cout << Verbose( 4) << "Adding line [" << LinesOnBoundaryCount << "|" << *(a->node) << " and " << *(b->node) << "." << endl;1234 cout << Verbose(3) << "Adding line between " << *(a->node) << " and " << *(b->node) << "." << endl; 1294 1235 BPS[0] = a; 1295 1236 BPS[1] = b; … … 1301 1242 }; 1302 1243 1303 /** Function adds triangle to global list.1304 * Furthermore , the triangle receives the next free id and id counter \a TrianglesOnBoundaryCount is increased.1244 /** Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm). 1245 * Furthermore it adds the triangle to all of its lines, in order to recognize those which are saturated later. 1305 1246 */ 1306 1247 void Tesselation::AddTesselationTriangle() … … 1311 1252 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1312 1253 TrianglesOnBoundaryCount++; 1313 1314 // set as last new triangle1315 LastTriangle = BTS;1316 1317 // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet1318 };1319 1320 /** Function adds triangle to global list.1321 * Furthermore, the triangle number is set to \a nr.1322 * \param nr triangle number1323 */1324 void Tesselation::AddTesselationTriangle(int nr)1325 {1326 cout << Verbose(1) << "Adding triangle to global TrianglesOnBoundary map." << endl;1327 1328 // add triangle to global map1329 TrianglesOnBoundary.insert(TrianglePair(nr, BTS));1330 1331 // set as last new triangle1332 LastTriangle = BTS;1333 1254 1334 1255 // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet … … 1351 1272 cout << Verbose(5) << *triangle->lines[i] << " is no more attached to any triangle, erasing." << endl; 1352 1273 RemoveTesselationLine(triangle->lines[i]); 1353 } else { 1354 cout << Verbose(5) << *triangle->lines[i] << " is still attached to another triangle: "; 1355 for(TriangleMap::iterator TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); TriangleRunner++) 1356 cout << "[" << (TriangleRunner->second)->Nr << "|" << *((TriangleRunner->second)->endpoints[0]) << ", " << *((TriangleRunner->second)->endpoints[1]) << ", " << *((TriangleRunner->second)->endpoints[2]) << "] \t"; 1357 cout << endl; 1358 // for (int j=0;j<2;j++) { 1359 // cout << Verbose(5) << "Lines of endpoint " << *(triangle->lines[i]->endpoints[j]) << ": "; 1360 // for(LineMap::iterator LineRunner = triangle->lines[i]->endpoints[j]->lines.begin(); LineRunner != triangle->lines[i]->endpoints[j]->lines.end(); LineRunner++) 1361 // cout << "[" << *(LineRunner->second) << "] \t"; 1362 // cout << endl; 1363 // } 1364 } 1365 triangle->lines[i] = NULL; // free'd or not: disconnect 1274 triangle->lines[i] = NULL; 1275 } else 1276 cout << Verbose(5) << *triangle->lines[i] << " is still attached to another triangle." << endl; 1366 1277 } else 1367 1278 cerr << "ERROR: This line " << i << " has already been free'd." << endl; … … 1383 1294 if (line == NULL) 1384 1295 return; 1385 // get other endpoint number forfinding copies of same line1296 // get other endpoint number of finding copies of same line 1386 1297 if (line->endpoints[1] != NULL) 1387 1298 Numbers[0] = line->endpoints[1]->Nr; … … 1410 1321 cout << Verbose(5) << *line->endpoints[i] << " has no more lines it's attached to, erasing." << endl; 1411 1322 RemoveTesselationPoint(line->endpoints[i]); 1412 } else { 1413 cout << Verbose(5) << *line->endpoints[i] << " has still lines it's attached to: "; 1414 for(LineMap::iterator LineRunner = line->endpoints[i]->lines.begin(); LineRunner != line->endpoints[i]->lines.end(); LineRunner++) 1415 cout << "[" << *(LineRunner->second) << "] \t"; 1416 cout << endl; 1417 } 1418 line->endpoints[i] = NULL; // free'd or not: disconnect 1323 line->endpoints[i] = NULL; 1324 } else 1325 cout << Verbose(5) << *line->endpoints[i] << " has still lines it's attached to." << endl; 1419 1326 } else 1420 1327 cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl; … … 1483 1390 } 1484 1391 // Only one of the triangle lines must be considered for the triangle count. 1485 //*out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;1486 //return adjacentTriangleCount;1392 *out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl; 1393 return adjacentTriangleCount; 1487 1394 } 1488 1395 } … … 1493 1400 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 1494 1401 return adjacentTriangleCount; 1495 };1496 1497 /** Checks whether the triangle consisting of the three points is already present.1498 * Searches for the points in Tesselation::PointsOnBoundary and checks their1499 * lines. If any of the three edges already has two triangles attached, false is1500 * returned.1501 * \param *out output stream for debugging1502 * \param *Candidates endpoints of the triangle candidate1503 * \return NULL - none found or pointer to triangle1504 */1505 class BoundaryTriangleSet * Tesselation::GetPresentTriangle(ofstream *out, TesselPoint *Candidates[3])1506 {1507 class BoundaryTriangleSet *triangle = NULL;1508 class BoundaryPointSet *Points[3];1509 1510 // builds a triangle point set (Points) of the end points1511 for (int i = 0; i < 3; i++) {1512 PointMap::iterator FindPoint = PointsOnBoundary.find(Candidates[i]->nr);1513 if (FindPoint != PointsOnBoundary.end()) {1514 Points[i] = FindPoint->second;1515 } else {1516 Points[i] = NULL;1517 }1518 }1519 1520 // checks lines between the points in the Points for their adjacent triangles1521 for (int i = 0; i < 3; i++) {1522 if (Points[i] != NULL) {1523 for (int j = i; j < 3; j++) {1524 if (Points[j] != NULL) {1525 LineMap::iterator FindLine = Points[i]->lines.find(Points[j]->node->nr);1526 for (; (FindLine != Points[i]->lines.end()) && (FindLine->first == Points[j]->node->nr); FindLine++) {1527 TriangleMap *triangles = &FindLine->second->triangles;1528 for (TriangleMap::iterator FindTriangle = triangles->begin(); FindTriangle != triangles->end(); FindTriangle++) {1529 if (FindTriangle->second->IsPresentTupel(Points)) {1530 if ((triangle == NULL) || (triangle->Nr > FindTriangle->second->Nr))1531 triangle = FindTriangle->second;1532 }1533 }1534 }1535 // Only one of the triangle lines must be considered for the triangle count.1536 //*out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;1537 //return adjacentTriangleCount;1538 }1539 }1540 }1541 }1542 1543 return triangle;1544 1402 }; 1545 1403 … … 1603 1461 CandidateList *OptCandidates = new CandidateList(); 1604 1462 for (int k=0;k<NDIM;k++) { 1605 Oben.Zero();1606 1463 Oben.x[k] = 1.; 1607 1464 FirstPoint = MaxPoint[k]; … … 1612 1469 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. 1613 1470 1614 FindSecondPointForTesselation(FirstPoint, Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...1471 FindSecondPointForTesselation(FirstPoint, NULL, Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_... 1615 1472 SecondPoint = OptCandidate; 1616 1473 if (SecondPoint == NULL) // have we found a second point? 1617 1474 continue; 1475 else 1476 cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n"; 1618 1477 1619 1478 helper.CopyVector(FirstPoint->node); … … 1637 1496 1638 1497 // adding point 1 and point 2 and add the line between them 1639 cout << Verbose(1) << "Coordinates of start node at " << *FirstPoint->node << "." << endl;1640 1498 AddTesselationPoint(FirstPoint, 0); 1641 cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n";1642 1499 AddTesselationPoint(SecondPoint, 1); 1643 1500 AddTesselationLine(TPS[0], TPS[1], 0); … … 1712 1569 * @param *LC LinkedCell structure with neighbouring points 1713 1570 */ 1714 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, LinkedCell *LC)1571 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, LinkedCell *LC) 1715 1572 { 1716 1573 cout << Verbose(0) << "Begin of FindNextSuitableTriangle\n"; … … 1747 1604 CircleRadius = RADIUS*RADIUS - radius/4.; 1748 1605 CirclePlaneNormal.Normalize(); 1749 //cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;1606 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 1750 1607 1751 1608 // construct old center … … 1834 1691 result = false; 1835 1692 } 1836 } else if ( (existentTrianglesCount >= 1) && (existentTrianglesCount <= 3)) { // If there is a planar region within the structure, we need this triangle a second time.1693 } else if (existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time. 1837 1694 AddTesselationPoint((*it)->point, 0); 1838 1695 AddTesselationPoint(BaseRay->endpoints[0]->node, 1); … … 1875 1732 // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point)) 1876 1733 BaseRay = BLS[0]; 1877 if ((BTS != NULL) && (BTS->NormalVector.NormSquared() < MYEPSILON)) {1878 *out << Verbose(1) << "CRITICAL: Triangle " << *BTS << " has zero normal vector!" << endl;1879 exit(255);1880 }1881 1882 1734 } 1883 1735 … … 1898 1750 * \param *out output stream for debugging 1899 1751 * \param *Base line to be flipped 1900 * \return NULL - con vex, otherwise endpoint that makes it concave1752 * \return NULL - concave, otherwise endpoint that makes it concave 1901 1753 */ 1902 1754 class BoundaryPointSet *Tesselation::IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base) … … 1975 1827 * \param *out output stream for debugging 1976 1828 * \param *Base line to be flipped 1977 * \return volume change due to flipping (0 - then no flipped occured)1978 */ 1979 doubleTesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base)1829 * \return true - line was changed, false - same line as before 1830 */ 1831 bool Tesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base) 1980 1832 { 1981 1833 class BoundaryLineSet *OtherBase; 1982 1834 Vector *ClosestPoint[2]; 1983 double volume;1984 1835 1985 1836 int m=0; … … 2001 1852 Distance.CopyVector(ClosestPoint[1]); 2002 1853 Distance.SubtractVector(ClosestPoint[0]); 2003 2004 // calculate volume2005 volume = CalculateVolumeofGeneralTetraeder(Base->endpoints[1]->node->node, OtherBase->endpoints[0]->node->node, OtherBase->endpoints[1]->node->node, Base->endpoints[0]->node->node);2006 1854 2007 1855 // delete the temporary other base line and the closest points … … 2018 1866 if (Base->triangles.size() < 2) { 2019 1867 *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl; 2020 return 0.;1868 return false; 2021 1869 } 2022 1870 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { … … 2028 1876 if (Distance.ScalarProduct(&BaseLineNormal) > MYEPSILON) { // Distance points outwards, hence OtherBase higher than Base -> flip 2029 1877 *out << Verbose(2) << "ACCEPT: Other base line would be higher: Flipping baseline." << endl; 2030 // calculate volume summand as a general tetraeder2031 return volume;1878 FlipBaseline(out, Base); 1879 return true; 2032 1880 } else { // Base higher than OtherBase -> do nothing 2033 1881 *out << Verbose(2) << "REJECT: Base line is higher: Nothing to do." << endl; 2034 return 0.; 2035 } 2036 } 1882 return false; 1883 } 1884 } 1885 }; 1886 1887 /** Returns the closest point on \a *Base with respect to \a *OtherBase. 1888 * \param *out output stream for debugging 1889 * \param *Base reference line 1890 * \param *OtherBase other base line 1891 * \return Vector on reference line that has closest distance 1892 */ 1893 Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase) 1894 { 1895 // construct the plane of the two baselines (i.e. take both their directional vectors) 1896 Vector Normal; 1897 Vector Baseline, OtherBaseline; 1898 Baseline.CopyVector(Base->endpoints[1]->node->node); 1899 Baseline.SubtractVector(Base->endpoints[0]->node->node); 1900 OtherBaseline.CopyVector(OtherBase->endpoints[1]->node->node); 1901 OtherBaseline.SubtractVector(OtherBase->endpoints[0]->node->node); 1902 Normal.CopyVector(&Baseline); 1903 Normal.VectorProduct(&OtherBaseline); 1904 Normal.Normalize(); 1905 *out << Verbose(4) << "First direction is " << Baseline << ", second direction is " << OtherBaseline << ", normal of intersection plane is " << Normal << "." << endl; 1906 1907 // project one offset point of OtherBase onto this plane (and add plane offset vector) 1908 Vector NewOffset; 1909 NewOffset.CopyVector(OtherBase->endpoints[0]->node->node); 1910 NewOffset.SubtractVector(Base->endpoints[0]->node->node); 1911 NewOffset.ProjectOntoPlane(&Normal); 1912 NewOffset.AddVector(Base->endpoints[0]->node->node); 1913 Vector NewDirection; 1914 NewDirection.CopyVector(&NewOffset); 1915 NewDirection.AddVector(&OtherBaseline); 1916 1917 // calculate the intersection between this projected baseline and Base 1918 Vector *Intersection = new Vector; 1919 Intersection->GetIntersectionOfTwoLinesOnPlane(out, Base->endpoints[0]->node->node, Base->endpoints[1]->node->node, &NewOffset, &NewDirection, &Normal); 1920 Normal.CopyVector(Intersection); 1921 Normal.SubtractVector(Base->endpoints[0]->node->node); 1922 *out << Verbose(3) << "Found closest point on " << *Base << " at " << *Intersection << ", factor in line is " << fabs(Normal.ScalarProduct(&Baseline)/Baseline.NormSquared()) << "." << endl; 1923 1924 return Intersection; 2037 1925 }; 2038 1926 … … 2042 1930 * \param *out output stream for debugging 2043 1931 * \param *Base line to be flipped 2044 * \return pointer to allocated new baseline - flipping successful, NULL- something went awry2045 */ 2046 class BoundaryLineSet *Tesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base)1932 * \return true - flipping successful, false - something went awry 1933 */ 1934 bool Tesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base) 2047 1935 { 2048 1936 class BoundaryLineSet *OldLines[4], *NewLine; … … 2058 1946 if (Base->triangles.size() < 2) { 2059 1947 *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl; 2060 return NULL;1948 return false; 2061 1949 } 2062 1950 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { … … 2094 1982 if (i<4) { 2095 1983 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl; 2096 return NULL;1984 return false; 2097 1985 } 2098 1986 for (int j=0;j<4;j++) 2099 1987 if (OldLines[j] == NULL) { 2100 1988 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl; 2101 return NULL;1989 return false; 2102 1990 } 2103 1991 for (int j=0;j<2;j++) 2104 1992 if (OldPoints[j] == NULL) { 2105 1993 *out << Verbose(1) << "ERROR: We have not gathered enough endpoints!" << endl; 2106 return NULL;1994 return false; 2107 1995 } 2108 1996 … … 2136 2024 BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[0]); 2137 2025 BTS->GetNormalVector(BaseLineNormal); 2138 AddTesselationTriangle(OldTriangleNrs[0]);2026 TrianglesOnBoundary.insert(TrianglePair(OldTriangleNrs[0], BTS)); 2139 2027 *out << Verbose(3) << "INFO: Created new triangle " << *BTS << "." << endl; 2140 2028 … … 2144 2032 BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[1]); 2145 2033 BTS->GetNormalVector(BaseLineNormal); 2146 AddTesselationTriangle(OldTriangleNrs[1]);2034 TrianglesOnBoundary.insert(TrianglePair(OldTriangleNrs[1], BTS)); 2147 2035 *out << Verbose(3) << "INFO: Created new triangle " << *BTS << "." << endl; 2148 2036 } else { 2149 2037 *out << Verbose(1) << "The four old lines do not connect, something's utterly wrong here!" << endl; 2150 return NULL;2038 return false; 2151 2039 } 2152 2040 2153 2041 *out << Verbose(1) << "End of FlipBaseline" << endl; 2154 return NewLine;2042 return true; 2155 2043 }; 2156 2044 … … 2158 2046 /** Finds the second point of starting triangle. 2159 2047 * \param *a first node 2048 * \param *Candidate pointer to candidate node on return 2160 2049 * \param Oben vector indicating the outside 2161 2050 * \param OptCandidate reference to recommended candidate on return … … 2164 2053 * \param *LC LinkedCell structure with neighbouring points 2165 2054 */ 2166 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC)2055 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, TesselPoint* Candidate, Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC) 2167 2056 { 2168 2057 cout << Verbose(2) << "Begin of FindSecondPointForTesselation" << endl; 2169 2058 Vector AngleCheck; 2170 class TesselPoint* Candidate = NULL;2171 2059 double norm = -1., angle; 2172 2060 LinkedNodes *List = NULL; … … 2303 2191 cout << Verbose(1) << "Begin of FindThirdPointForTesselation" << endl; 2304 2192 2305 cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;2193 //cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl; 2306 2194 2307 2195 // construct center of circle … … 2328 2216 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2329 2217 if (fabs(radius - CircleRadius) < HULLEPSILON) { 2330 //cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;2331 2218 2332 2219 // check SearchDirection … … 2505 2392 TesselPoint *trianglePoints[3]; 2506 2393 TesselPoint *SecondPoint = NULL; 2507 list<BoundaryTriangleSet*> *triangles = NULL;2508 2394 2509 2395 if (LinesOnBoundary.empty()) { … … 2516 2402 // check whether closest point is "too close" :), then it's inside 2517 2403 if (trianglePoints[0] == NULL) { 2518 *out << Verbose( 2) << "Is the only point, no one else is closeby." << endl;2404 *out << Verbose(1) << "Is the only point, no one else is closeby." << endl; 2519 2405 return NULL; 2520 2406 } 2521 2407 if (trianglePoints[0]->node->DistanceSquared(x) < MYEPSILON) { 2522 *out << Verbose(3) << "Point is right on a tesselation point, no nearest triangle." << endl; 2523 PointMap::iterator PointRunner = PointsOnBoundary.find(trianglePoints[0]->nr); 2524 triangles = new list<BoundaryTriangleSet*>; 2525 if (PointRunner != PointsOnBoundary.end()) { 2526 for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++) 2527 for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++) 2528 triangles->push_back(TriangleRunner->second); 2529 triangles->sort(); 2530 triangles->unique(); 2531 } else { 2532 PointRunner = PointsOnBoundary.find(SecondPoint->nr); 2533 trianglePoints[0] = SecondPoint; 2534 if (PointRunner != PointsOnBoundary.end()) { 2535 for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++) 2536 for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++) 2537 triangles->push_back(TriangleRunner->second); 2538 triangles->sort(); 2539 triangles->unique(); 2540 } else { 2541 *out << Verbose(1) << "ERROR: I cannot find a boundary point to the tessel point " << *trianglePoints[0] << "." << endl; 2542 return NULL; 2543 } 2544 } 2545 } else { 2546 list<TesselPoint*> *connectedClosestPoints = GetCircleOfConnectedPoints(out, trianglePoints[0], x); 2547 trianglePoints[1] = connectedClosestPoints->front(); 2548 trianglePoints[2] = connectedClosestPoints->back(); 2549 for (int i=0;i<3;i++) { 2550 if (trianglePoints[i] == NULL) { 2551 *out << Verbose(1) << "ERROR: IsInnerPoint encounters serious error, point " << i << " not found." << endl; 2552 } 2553 //*out << Verbose(2) << "List of triangle points:" << endl; 2554 //*out << Verbose(3) << *trianglePoints[i] << endl; 2555 } 2556 2557 triangles = FindTriangles(trianglePoints); 2558 *out << Verbose(2) << "List of possible triangles:" << endl; 2559 for(list<BoundaryTriangleSet*>::iterator Runner = triangles->begin(); Runner != triangles->end(); Runner++) 2560 *out << Verbose(3) << **Runner << endl; 2561 2562 delete(connectedClosestPoints); 2563 } 2408 *out << Verbose(1) << "Point is right on a tesselation point, no nearest triangle." << endl; 2409 return NULL; 2410 } 2411 list<TesselPoint*> *connectedPoints = GetCircleOfConnectedPoints(out, trianglePoints[0]); 2412 list<TesselPoint*> *connectedClosestPoints = GetNeighboursOnCircleOfConnectedPoints(out, connectedPoints, trianglePoints[0], x); 2413 delete(connectedPoints); 2414 trianglePoints[1] = connectedClosestPoints->front(); 2415 trianglePoints[2] = connectedClosestPoints->back(); 2416 for (int i=0;i<3;i++) { 2417 if (trianglePoints[i] == NULL) { 2418 *out << Verbose(1) << "IsInnerPoint encounters serious error, point " << i << " not found." << endl; 2419 } 2420 //*out << Verbose(1) << "List of possible points:" << endl; 2421 //*out << Verbose(2) << *trianglePoints[i] << endl; 2422 } 2423 2424 list<BoundaryTriangleSet*> *triangles = FindTriangles(trianglePoints); 2425 2426 delete(connectedClosestPoints); 2564 2427 2565 2428 if (triangles->empty()) { 2566 *out << Verbose(0) << "ERROR: There is no nearest triangle. Please check the tesselation structure."; 2567 delete(triangles); 2429 *out << Verbose(0) << "Error: There is no nearest triangle. Please check the tesselation structure."; 2568 2430 return NULL; 2569 2431 } else … … 2581 2443 class BoundaryTriangleSet *result = NULL; 2582 2444 list<BoundaryTriangleSet*> *triangles = FindClosestTrianglesToPoint(out, x, LC); 2583 Vector Center;2584 2445 2585 2446 if (triangles == NULL) 2586 2447 return NULL; 2587 2448 2588 if (triangles->size() == 1) { // there is no degenerate case 2449 if (x->ScalarProduct(&triangles->front()->NormalVector) < 0) 2450 result = triangles->back(); 2451 else 2589 2452 result = triangles->front(); 2590 *out << Verbose(2) << "Normal Vector of this triangle is " << result->NormalVector << "." << endl; 2591 } else { 2592 result = triangles->front(); 2593 result->GetCenter(&Center); 2594 Center.SubtractVector(x); 2595 *out << Verbose(2) << "Normal Vector of this front side is " << result->NormalVector << "." << endl; 2596 if (Center.ScalarProduct(&result->NormalVector) < 0) { 2597 result = triangles->back(); 2598 *out << Verbose(2) << "Normal Vector of this back side is " << result->NormalVector << "." << endl; 2599 if (Center.ScalarProduct(&result->NormalVector) < 0) { 2600 *out << Verbose(1) << "ERROR: Front and back side yield NormalVector in wrong direction!" << endl; 2601 } 2602 } 2603 } 2453 2604 2454 delete(triangles); 2605 2455 return result; … … 2616 2466 { 2617 2467 class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, &Point, LC); 2618 Vector Center; 2619 2620 if (result == NULL) {// is boundary point or only point in point cloud? 2621 *out << Verbose(1) << Point << " is the only point in vicinity." << endl; 2468 if (result == NULL) 2469 return true; 2470 if (Point.ScalarProduct(&result->NormalVector) < 0) 2471 return true; 2472 else 2622 2473 return false; 2623 }2624 2625 result->GetCenter(&Center);2626 *out << Verbose(3) << "INFO: Central point of the triangle is " << Center << "." << endl;2627 Center.SubtractVector(&Point);2628 *out << Verbose(3) << "INFO: Vector from center to point to test is " << Center << "." << endl;2629 if (Center.ScalarProduct(&result->NormalVector) > -MYEPSILON) {2630 *out << Verbose(1) << Point << " is an inner point." << endl;2631 return true;2632 } else {2633 *out << Verbose(1) << Point << " is NOT an inner point." << endl;2634 return false;2635 }2636 2474 } 2637 2475 … … 2645 2483 bool Tesselation::IsInnerPoint(ofstream *out, TesselPoint *Point, LinkedCell* LC) 2646 2484 { 2647 return IsInnerPoint(out, *(Point->node), LC); 2485 class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, Point->node, LC); 2486 if (result == NULL) 2487 return true; 2488 if (Point->node->ScalarProduct(&result->NormalVector) < 0) 2489 return true; 2490 else 2491 return false; 2648 2492 } 2649 2493 … … 2652 2496 * @param *Point of which get all connected points 2653 2497 * 2654 * @return set of the all points linked to the provided one2655 */ 2656 set<TesselPoint*> * Tesselation::GetAllConnectedPoints(ofstream *out, TesselPoint* Point)2657 { 2658 set<TesselPoint*> *connectedPoints = new set<TesselPoint*>;2498 * @return list of the all points linked to the provided one 2499 */ 2500 list<TesselPoint*> * Tesselation::GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point) 2501 { 2502 list<TesselPoint*> *connectedPoints = new list<TesselPoint*>; 2659 2503 class BoundaryPointSet *ReferencePoint = NULL; 2660 2504 TesselPoint* current; … … 2666 2510 ReferencePoint = PointRunner->second; 2667 2511 } else { 2668 *out << Verbose(2) << " GetAllConnectedPoints() could not find the BoundaryPoint belonging to " << *Point << "." << endl;2512 *out << Verbose(2) << "getCircleOfConnectedPoints() could not find the BoundaryPoint belonging to " << *Point << "." << endl; 2669 2513 ReferencePoint = NULL; 2670 2514 } 2671 2515 2672 // little trick so that we look just through lines connect to the BoundaryPoint 2516 // little trick so that we look just through lines connect to the BoundaryPoint 2673 2517 // OR fall-back to look through all lines if there is no such BoundaryPoint 2674 2518 LineMap *Lines = &LinesOnBoundary; … … 2677 2521 LineMap::iterator findLines = Lines->begin(); 2678 2522 while (findLines != Lines->end()) { 2679 takePoint = false;2680 2681 if (findLines->second->endpoints[0]->Nr == Point->nr) {2682 takePoint = true;2683 current = findLines->second->endpoints[1]->node;2684 } else if (findLines->second->endpoints[1]->Nr == Point->nr) {2685 takePoint = true;2686 current = findLines->second->endpoints[0]->node;2687 }2688 2689 if (takePoint) {2690 *out << Verbose(5) << "INFO: Endpoint " << *current << " of line " << *(findLines->second) << " is enlisted." << endl;2691 connectedPoints->insert(current);2692 }2693 2694 findLines++;2523 takePoint = false; 2524 2525 if (findLines->second->endpoints[0]->Nr == Point->nr) { 2526 takePoint = true; 2527 current = findLines->second->endpoints[1]->node; 2528 } else if (findLines->second->endpoints[1]->Nr == Point->nr) { 2529 takePoint = true; 2530 current = findLines->second->endpoints[0]->node; 2531 } 2532 2533 if (takePoint) { 2534 *out << Verbose(3) << "INFO: Endpoint " << *current << " of line " << *(findLines->second) << " is taken into the circle." << endl; 2535 connectedPoints->push_back(current); 2536 } 2537 2538 findLines++; 2695 2539 } 2696 2540 … … 2699 2543 return NULL; 2700 2544 } 2701 2702 2545 return connectedPoints; 2703 }; 2704 2705 2706 /** Gets all points connected to the provided point by triangulation lines, ordered such that we have the circle round the point. 2546 } 2547 2548 /** Gets the two neighbouring points with respect to a reference line to the provided point. 2707 2549 * Maps them down onto the plane designated by the axis \a *Point and \a *Reference. The center of all points 2708 2550 * connected in the tesselation to \a *Point is mapped to spherical coordinates with the zero angle being given … … 2711 2553 * 2712 2554 * @param *out output stream for debugging 2555 * @param *connectedPoints list of connected points to the central \a *Point 2713 2556 * @param *Point of which get all connected points 2714 * @param *Reference Reference vector for zero angle or NULL for no preference 2715 * @return list of the all points linked to the provided one 2716 */ 2717 list<TesselPoint*> * Tesselation::GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point, Vector *Reference) 2557 * @param *Reference Vector to be checked whether it is an inner point 2558 * 2559 * @return list of the two points linked to the provided one and closest to the point to be checked, 2560 */ 2561 list<TesselPoint*> * Tesselation::GetNeighboursOnCircleOfConnectedPoints(ofstream *out, list<TesselPoint*> *connectedPoints, TesselPoint* Point, Vector* Reference) 2718 2562 { 2719 2563 map<double, TesselPoint*> anglesOfPoints; 2720 set<TesselPoint*> *connectedPoints = GetAllConnectedPoints(out, Point); 2721 list<TesselPoint*> *connectedCircle = new list<TesselPoint*>; 2722 Vector center; 2723 Vector PlaneNormal; 2724 Vector AngleZero; 2725 Vector OrthogonalVector; 2726 Vector helper; 2564 map<double, TesselPoint*>::iterator runner; 2565 ; 2566 Vector center, PlaneNormal, OrthogonalVector, helper, AngleZero; 2567 2568 if (connectedPoints->size() == 0) { // if have not found any points 2569 *out << Verbose(1) << "ERROR: We have not found any connected points to " << *Point<< "." << endl; 2570 return NULL; 2571 } 2727 2572 2728 2573 // calculate central point 2729 for ( set<TesselPoint*>::iterator TesselRunner = connectedPoints->begin(); TesselRunner != connectedPoints->end(); TesselRunner++)2574 for (list<TesselPoint*>::iterator TesselRunner = connectedPoints->begin(); TesselRunner != connectedPoints->end(); TesselRunner++) 2730 2575 center.AddVector((*TesselRunner)->node); 2731 2576 //*out << "Summed vectors " << center << "; number of points " << connectedPoints.size() … … 2741 2586 2742 2587 // construct one orthogonal vector 2743 if (Reference != NULL) 2744 AngleZero.CopyVector(Reference); 2745 else 2746 AngleZero.CopyVector((*connectedPoints->begin())->node); 2588 AngleZero.CopyVector(Reference); 2747 2589 AngleZero.SubtractVector(Point->node); 2748 2590 AngleZero.ProjectOntoPlane(&PlaneNormal); … … 2752 2594 2753 2595 // go through all connected points and calculate angle 2754 for ( set<TesselPoint*>::iterator listRunner = connectedPoints->begin(); listRunner != connectedPoints->end(); listRunner++) {2596 for (list<TesselPoint*>::iterator listRunner = connectedPoints->begin(); listRunner != connectedPoints->end(); listRunner++) { 2755 2597 helper.CopyVector((*listRunner)->node); 2756 2598 helper.SubtractVector(Point->node); 2757 2599 helper.ProjectOntoPlane(&PlaneNormal); 2758 2600 double angle = GetAngle(helper, AngleZero, OrthogonalVector); 2759 *out << Verbose( 3) << "INFO: Calculated angle is " << angle << " for point " << **listRunner << "." << endl;2601 *out << Verbose(2) << "INFO: Calculated angle is " << angle << " for point " << **listRunner << "." << endl; 2760 2602 anglesOfPoints.insert(pair<double, TesselPoint*>(angle, (*listRunner))); 2761 2603 } 2762 2604 2763 for(map<double, TesselPoint*>::iterator AngleRunner = anglesOfPoints.begin(); AngleRunner != anglesOfPoints.end(); AngleRunner++) { 2764 connectedCircle->push_back(AngleRunner->second); 2765 } 2766 2767 delete(connectedPoints); 2768 return connectedCircle; 2605 list<TesselPoint*> *result = new list<TesselPoint*>; 2606 runner = anglesOfPoints.begin(); 2607 result->push_back(runner->second); 2608 runner = anglesOfPoints.end(); 2609 runner--; 2610 result->push_back(runner->second); 2611 2612 *out << Verbose(2) << "List of closest points has " << result->size() << " elements, which are " 2613 << *(result->front()) << " and " << *(result->back()) << endl; 2614 2615 return result; 2769 2616 } 2770 2617 2771 /** Gets all points connected to the provided point by triangulation lines, ordered such that we walk along a closed path.2772 *2773 * @param *out output stream for debugging2774 * @param *Point of which get all connected points2775 * @return list of the all points linked to the provided one2776 */2777 list<list<TesselPoint*> *> * Tesselation::GetPathsOfConnectedPoints(ofstream *out, TesselPoint* Point)2778 {2779 map<double, TesselPoint*> anglesOfPoints;2780 list<list<TesselPoint*> *> *ListOfPaths = new list<list<TesselPoint*> *>;2781 list<TesselPoint*> *connectedPath = NULL;2782 Vector center;2783 Vector PlaneNormal;2784 Vector AngleZero;2785 Vector OrthogonalVector;2786 Vector helper;2787 class BoundaryPointSet *ReferencePoint = NULL;2788 class BoundaryPointSet *CurrentPoint = NULL;2789 class BoundaryTriangleSet *triangle = NULL;2790 class BoundaryLineSet *CurrentLine = NULL;2791 class BoundaryLineSet *StartLine = NULL;2792 2793 // find the respective boundary point2794 PointMap::iterator PointRunner = PointsOnBoundary.find(Point->nr);2795 if (PointRunner != PointsOnBoundary.end()) {2796 ReferencePoint = PointRunner->second;2797 } else {2798 *out << Verbose(2) << "ERROR: GetPathOfConnectedPoints() could not find the BoundaryPoint belonging to " << *Point << "." << endl;2799 return NULL;2800 }2801 2802 map <class BoundaryLineSet *, bool> TouchedLine;2803 map <class BoundaryTriangleSet *, bool> TouchedTriangle;2804 map <class BoundaryLineSet *, bool>::iterator LineRunner;2805 map <class BoundaryTriangleSet *, bool>::iterator TriangleRunner;2806 for (LineMap::iterator Runner = ReferencePoint->lines.begin(); Runner != ReferencePoint->lines.end(); Runner++) {2807 TouchedLine.insert( pair <class BoundaryLineSet *, bool>(Runner->second, false) );2808 for (TriangleMap::iterator Sprinter = Runner->second->triangles.begin(); Sprinter != Runner->second->triangles.end(); Sprinter++)2809 TouchedTriangle.insert( pair <class BoundaryTriangleSet *, bool>(Sprinter->second, false) );2810 }2811 if (!ReferencePoint->lines.empty()) {2812 for (LineMap::iterator runner = ReferencePoint->lines.begin(); runner != ReferencePoint->lines.end(); runner++) {2813 LineRunner = TouchedLine.find(runner->second);2814 if (LineRunner == TouchedLine.end()) {2815 *out << Verbose(2) << "ERROR: I could not find " << *runner->second << " in the touched list." << endl;2816 } else if (!LineRunner->second) {2817 LineRunner->second = true;2818 connectedPath = new list<TesselPoint*>;2819 triangle = NULL;2820 CurrentLine = runner->second;2821 StartLine = CurrentLine;2822 CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint);2823 *out << Verbose(3)<< "INFO: Beginning path retrieval at " << *CurrentPoint << " of line " << *CurrentLine << "." << endl;2824 do {2825 // push current one2826 *out << Verbose(3) << "INFO: Putting " << *CurrentPoint << " at end of path." << endl;2827 connectedPath->push_back(CurrentPoint->node);2828 2829 // find next triangle2830 for (TriangleMap::iterator Runner = CurrentLine->triangles.begin(); Runner != CurrentLine->triangles.end(); Runner++) {2831 *out << Verbose(3) << "INFO: Inspecting triangle " << *Runner->second << "." << endl;2832 if ((Runner->second != triangle)) { // look for first triangle not equal to old one2833 triangle = Runner->second;2834 TriangleRunner = TouchedTriangle.find(triangle);2835 if (TriangleRunner != TouchedTriangle.end()) {2836 if (!TriangleRunner->second) {2837 TriangleRunner->second = true;2838 *out << Verbose(3) << "INFO: Connecting triangle is " << *triangle << "." << endl;2839 break;2840 } else {2841 *out << Verbose(3) << "INFO: Skipping " << *triangle << ", as we have already visited it." << endl;2842 triangle = NULL;2843 }2844 } else {2845 *out << Verbose(2) << "ERROR: I could not find " << *triangle << " in the touched list." << endl;2846 triangle = NULL;2847 }2848 }2849 }2850 if (triangle == NULL)2851 break;2852 // find next line2853 for (int i=0;i<3;i++) {2854 if ((triangle->lines[i] != CurrentLine) && (triangle->lines[i]->ContainsBoundaryPoint(ReferencePoint))) { // not the current line and still containing Point2855 CurrentLine = triangle->lines[i];2856 *out << Verbose(3) << "INFO: Connecting line is " << *CurrentLine << "." << endl;2857 break;2858 }2859 }2860 LineRunner = TouchedLine.find(CurrentLine);2861 if (LineRunner == TouchedLine.end())2862 *out << Verbose(2) << "ERROR: I could not find " << *CurrentLine << " in the touched list." << endl;2863 else2864 LineRunner->second = true;2865 // find next point2866 CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint);2867 2868 } while (CurrentLine != StartLine);2869 // last point is missing, as it's on start line2870 *out << Verbose(3) << "INFO: Putting " << *CurrentPoint << " at end of path." << endl;2871 if (StartLine->GetOtherEndpoint(ReferencePoint)->node != connectedPath->back())2872 connectedPath->push_back(StartLine->GetOtherEndpoint(ReferencePoint)->node);2873 2874 ListOfPaths->push_back(connectedPath);2875 } else {2876 *out << Verbose(3) << "INFO: Skipping " << *runner->second << ", as we have already visited it." << endl;2877 }2878 }2879 } else {2880 *out << Verbose(1) << "ERROR: There are no lines attached to " << *ReferencePoint << "." << endl;2881 }2882 2883 return ListOfPaths;2884 }2885 2886 /** Gets all closed paths on the circle of points connected to the provided point by triangulation lines, if this very point is removed.2887 * From GetPathsOfConnectedPoints() extracts all single loops of intracrossing paths in the list of closed paths.2888 * @param *out output stream for debugging2889 * @param *Point of which get all connected points2890 * @return list of the closed paths2891 */2892 list<list<TesselPoint*> *> * Tesselation::GetClosedPathsOfConnectedPoints(ofstream *out, TesselPoint* Point)2893 {2894 list<list<TesselPoint*> *> *ListofPaths = GetPathsOfConnectedPoints(out, Point);2895 list<list<TesselPoint*> *> *ListofClosedPaths = new list<list<TesselPoint*> *>;2896 list<TesselPoint*> *connectedPath = NULL;2897 list<TesselPoint*> *newPath = NULL;2898 int count = 0;2899 2900 2901 list<TesselPoint*>::iterator CircleRunner;2902 list<TesselPoint*>::iterator CircleStart;2903 2904 for(list<list<TesselPoint*> *>::iterator ListRunner = ListofPaths->begin(); ListRunner != ListofPaths->end(); ListRunner++) {2905 connectedPath = *ListRunner;2906 2907 *out << Verbose(2) << "INFO: Current path is " << connectedPath << "." << endl;2908 2909 // go through list, look for reappearance of starting Point and count2910 CircleStart = connectedPath->begin();2911 2912 // go through list, look for reappearance of starting Point and create list2913 list<TesselPoint*>::iterator Marker = CircleStart;2914 for (CircleRunner = CircleStart; CircleRunner != connectedPath->end(); CircleRunner++) {2915 if ((*CircleRunner == *CircleStart) && (CircleRunner != CircleStart)) { // is not the very first point2916 // we have a closed circle from Marker to new Marker2917 *out << Verbose(3) << count+1 << ". closed path consists of: ";2918 newPath = new list<TesselPoint*>;2919 list<TesselPoint*>::iterator CircleSprinter = Marker;2920 for (; CircleSprinter != CircleRunner; CircleSprinter++) {2921 newPath->push_back(*CircleSprinter);2922 *out << (**CircleSprinter) << " <-> ";2923 }2924 *out << ".." << endl;2925 count++;2926 Marker = CircleRunner;2927 2928 // add to list2929 ListofClosedPaths->push_back(newPath);2930 }2931 }2932 }2933 *out << Verbose(3) << "INFO: " << count << " closed additional path(s) have been created." << endl;2934 2935 // delete list of paths2936 while (!ListofPaths->empty()) {2937 connectedPath = *(ListofPaths->begin());2938 ListofPaths->remove(connectedPath);2939 delete(connectedPath);2940 }2941 delete(ListofPaths);2942 2943 // exit2944 return ListofClosedPaths;2945 };2946 2947 2948 /** Gets all belonging triangles for a given BoundaryPointSet.2949 * \param *out output stream for debugging2950 * \param *Point BoundaryPoint2951 * \return pointer to allocated list of triangles2952 */2953 set<BoundaryTriangleSet*> *Tesselation::GetAllTriangles(ofstream *out, class BoundaryPointSet *Point)2954 {2955 set<BoundaryTriangleSet*> *connectedTriangles = new set<BoundaryTriangleSet*>;2956 2957 if (Point == NULL) {2958 *out << Verbose(1) << "ERROR: Point given is NULL." << endl;2959 } else {2960 // go through its lines and insert all triangles2961 for (LineMap::iterator LineRunner = Point->lines.begin(); LineRunner != Point->lines.end(); LineRunner++)2962 for (TriangleMap::iterator TriangleRunner = (LineRunner->second)->triangles.begin(); TriangleRunner != (LineRunner->second)->triangles.end(); TriangleRunner++) {2963 connectedTriangles->insert(TriangleRunner->second);2964 }2965 }2966 2967 return connectedTriangles;2968 };2969 2970 2971 2618 /** Removes a boundary point from the envelope while keeping it closed. 2972 * We remove the old triangles connected to the point and re-create new triangles to close the surface following this ansatz: 2973 * -# a closed path(s) of boundary points surrounding the point to be removed is constructed 2974 * -# on each closed path, we pick three adjacent points, create a triangle with them and subtract the middle point from the path 2975 * -# we advance two points (i.e. the next triangle will start at the ending point of the last triangle) and continue as before 2976 * -# the surface is closed, when the path is empty 2977 * Thereby, we (hopefully) make sure that the removed points remains beneath the surface (this is checked via IsInnerPoint eventually). 2619 * We create new triangles and remove the old ones connected to the point. 2978 2620 * \param *out output stream for debugging 2979 2621 * \param *point point to be removed … … 2983 2625 class BoundaryLineSet *line = NULL; 2984 2626 class BoundaryTriangleSet *triangle = NULL; 2985 Vector OldPoint, NormalVector;2627 Vector OldPoint, TetraederVector[3]; 2986 2628 double volume = 0; 2629 int *numbers = NULL; 2987 2630 int count = 0; 2631 int i; 2988 2632 2989 2633 if (point == NULL) { … … 3001 2645 return 0.; 3002 2646 } 3003 3004 list<list<TesselPoint*> *> *ListOfClosedPaths = GetClosedPathsOfConnectedPoints(out, point->node); 3005 list<TesselPoint*> *connectedPath = NULL; 3006 3007 // gather all triangles 2647 list<TesselPoint*> *CircleofPoints = GetCircleOfConnectedPoints(out, point->node); 2648 2649 // remove all triangles 3008 2650 for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) 3009 2651 count+=LineRunner->second->triangles.size(); 3010 map<class BoundaryTriangleSet *, int> Candidates; 3011 for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) { 2652 numbers = new int[count]; 2653 class BoundaryTriangleSet **Candidates = new BoundaryTriangleSet*[count]; 2654 i=0; 2655 for (LineMap::iterator LineRunner = point->lines.begin(); (point != NULL) && (LineRunner != point->lines.end()); LineRunner++) { 3012 2656 line = LineRunner->second; 3013 2657 for (TriangleMap::iterator TriangleRunner = line->triangles.begin(); TriangleRunner != line->triangles.end(); TriangleRunner++) { 3014 2658 triangle = TriangleRunner->second; 3015 Candidates.insert( pair<class BoundaryTriangleSet *, int> (triangle, triangle->Nr) ); 3016 } 3017 } 3018 3019 // remove all triangles 3020 count=0; 3021 NormalVector.Zero(); 3022 for (map<class BoundaryTriangleSet *, int>::iterator Runner = Candidates.begin(); Runner != Candidates.end(); Runner++) { 3023 *out << Verbose(3) << "INFO: Removing triangle " << *(Runner->first) << "." << endl; 3024 NormalVector.SubtractVector(&Runner->first->NormalVector); // has to point inward 3025 RemoveTesselationTriangle(Runner->first); 3026 count++; 3027 } 3028 *out << Verbose(1) << count << " triangles were removed." << endl; 3029 3030 list<list<TesselPoint*> *>::iterator ListAdvance = ListOfClosedPaths->begin(); 3031 list<list<TesselPoint*> *>::iterator ListRunner = ListAdvance; 3032 map<class BoundaryTriangleSet *, int>::iterator NumberRunner = Candidates.begin(); 3033 list<TesselPoint*>::iterator StartNode, MiddleNode, EndNode; 3034 double angle; 3035 double smallestangle; 3036 Vector Point, Reference, OrthogonalVector; 3037 if (count > 2) { // less than three triangles, then nothing will be created 3038 class TesselPoint *TriangleCandidates[3]; 3039 count = 0; 3040 for ( ; ListRunner != ListOfClosedPaths->end(); ListRunner = ListAdvance) { // go through all closed paths 3041 if (ListAdvance != ListOfClosedPaths->end()) 3042 ListAdvance++; 3043 3044 connectedPath = *ListRunner; 3045 3046 // re-create all triangles by going through connected points list 3047 list<class BoundaryLineSet *> NewLines; 3048 for (;!connectedPath->empty();) { 3049 // search middle node with widest angle to next neighbours 3050 EndNode = connectedPath->end(); 3051 smallestangle = 0.; 3052 for (MiddleNode = connectedPath->begin(); MiddleNode != connectedPath->end(); MiddleNode++) { 3053 cout << Verbose(3) << "INFO: MiddleNode is " << **MiddleNode << "." << endl; 3054 // construct vectors to next and previous neighbour 3055 StartNode = MiddleNode; 3056 if (StartNode == connectedPath->begin()) 3057 StartNode = connectedPath->end(); 3058 StartNode--; 3059 //cout << Verbose(3) << "INFO: StartNode is " << **StartNode << "." << endl; 3060 Point.CopyVector((*StartNode)->node); 3061 Point.SubtractVector((*MiddleNode)->node); 3062 StartNode = MiddleNode; 3063 StartNode++; 3064 if (StartNode == connectedPath->end()) 3065 StartNode = connectedPath->begin(); 3066 //cout << Verbose(3) << "INFO: EndNode is " << **StartNode << "." << endl; 3067 Reference.CopyVector((*StartNode)->node); 3068 Reference.SubtractVector((*MiddleNode)->node); 3069 OrthogonalVector.CopyVector((*MiddleNode)->node); 3070 OrthogonalVector.SubtractVector(&OldPoint); 3071 OrthogonalVector.MakeNormalVector(&Reference); 3072 angle = GetAngle(Point, Reference, OrthogonalVector); 3073 //if (angle < M_PI) // no wrong-sided triangles, please? 3074 if(fabs(angle - M_PI) < fabs(smallestangle - M_PI)) { // get straightest angle (i.e. construct those triangles with smallest area first) 3075 smallestangle = angle; 3076 EndNode = MiddleNode; 2659 Candidates[i] = triangle; 2660 numbers[i++] = triangle->Nr; 2661 } 2662 } 2663 for (int j=0;j<i;j++) { 2664 RemoveTesselationTriangle(Candidates[j]); 2665 } 2666 delete[](Candidates); 2667 *out << Verbose(1) << i << " triangles were removed." << endl; 2668 2669 // re-create all triangles by going through connected points list 2670 list<TesselPoint*>::iterator CircleRunner = CircleofPoints->begin(); 2671 list<TesselPoint*>::iterator OtherCircleRunner = CircleofPoints->begin(); 2672 class TesselPoint *CentralNode = *CircleRunner; 2673 // advance two with CircleRunner and one with OtherCircleRunner 2674 CircleRunner++; 2675 CircleRunner++; 2676 OtherCircleRunner++; 2677 i=0; 2678 cout << Verbose(2) << "INFO: CentralNode is " << *CentralNode << "." << endl; 2679 for (; (OtherCircleRunner != CircleofPoints->end()) && (CircleRunner != CircleofPoints->end()); (CircleRunner++), (OtherCircleRunner++)) { 2680 cout << Verbose(3) << "INFO: CircleRunner's node is " << **CircleRunner << "." << endl; 2681 cout << Verbose(3) << "INFO: OtherCircleRunner's node is " << **OtherCircleRunner << "." << endl; 2682 *out << Verbose(4) << "Adding new triangle points."<< endl; 2683 AddTesselationPoint(CentralNode, 0); 2684 AddTesselationPoint(*OtherCircleRunner, 1); 2685 AddTesselationPoint(*CircleRunner, 2); 2686 *out << Verbose(4) << "Adding new triangle lines."<< endl; 2687 AddTesselationLine(TPS[0], TPS[1], 0); 2688 AddTesselationLine(TPS[0], TPS[2], 1); 2689 AddTesselationLine(TPS[1], TPS[2], 2); 2690 BTS = new class BoundaryTriangleSet(BLS, numbers[i]); 2691 TrianglesOnBoundary.insert(TrianglePair(numbers[i], BTS)); 2692 *out << Verbose(4) << "Created triangle " << *BTS << "." << endl; 2693 // calculate volume summand as a general tetraeder 2694 for (int j=0;j<3;j++) { 2695 TetraederVector[j].CopyVector(TPS[j]->node->node); 2696 TetraederVector[j].SubtractVector(&OldPoint); 2697 } 2698 OldPoint.CopyVector(&TetraederVector[0]); 2699 OldPoint.VectorProduct(&TetraederVector[1]); 2700 volume += 1./6. * fabs(OldPoint.ScalarProduct(&TetraederVector[2])); 2701 // advance number 2702 i++; 2703 if (i >= count) 2704 *out << Verbose(2) << "WARNING: Maximum of numbers reached!" << endl; 2705 } 2706 *out << Verbose(1) << i << " triangles were created." << endl; 2707 2708 delete[](numbers); 2709 2710 return volume; 2711 }; 2712 2713 /** Checks for a new special triangle whether one of its edges is already present with one one triangle connected. 2714 * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not 2715 * make it bigger (i.e. closing one (the baseline) and opening two new ones). 2716 * \param TPS[3] nodes of the triangle 2717 * \return true - there is such a line (i.e. creation of degenerated triangle is valid), false - no such line (don't create) 2718 */ 2719 bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3]) 2720 { 2721 bool result = false; 2722 int counter = 0; 2723 2724 // check all three points 2725 for (int i=0;i<3;i++) 2726 for (int j=i+1; j<3; j++) { 2727 if (nodes[i]->lines.find(nodes[j]->node->nr) != nodes[i]->lines.end()) { // there already is a line 2728 LineMap::iterator FindLine; 2729 pair<LineMap::iterator,LineMap::iterator> FindPair; 2730 FindPair = nodes[i]->lines.equal_range(nodes[j]->node->nr); 2731 for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) { 2732 // If there is a line with less than two attached triangles, we don't need a new line. 2733 if (FindLine->second->triangles.size() < 2) { 2734 counter++; 2735 break; // increase counter only once per edge 2736 } 2737 } 2738 } else { // no line 2739 cout << Verbose(1) << "The line between " << nodes[i] << " and " << nodes[j] << " is not yet present, hence no need for a degenerate triangle." << endl; 2740 result = true; 2741 } 2742 } 2743 if (counter > 1) { 2744 cout << Verbose(2) << "INFO: Degenerate triangle is ok, at least two, here " << counter << ", existing lines are used." << endl; 2745 result = true; 2746 } 2747 return result; 2748 }; 2749 2750 2751 /** Sort function for the candidate list. 2752 */ 2753 bool SortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2) 2754 { 2755 Vector BaseLineVector, OrthogonalVector, helper; 2756 if (candidate1->BaseLine != candidate2->BaseLine) { // sanity check 2757 cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl; 2758 //return false; 2759 exit(1); 2760 } 2761 // create baseline vector 2762 BaseLineVector.CopyVector(candidate1->BaseLine->endpoints[1]->node->node); 2763 BaseLineVector.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node); 2764 BaseLineVector.Normalize(); 2765 2766 // 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!) 2767 helper.CopyVector(candidate1->BaseLine->endpoints[0]->node->node); 2768 helper.SubtractVector(candidate1->point->node); 2769 OrthogonalVector.CopyVector(&helper); 2770 helper.VectorProduct(&BaseLineVector); 2771 OrthogonalVector.SubtractVector(&helper); 2772 OrthogonalVector.Normalize(); 2773 2774 // calculate both angles and correct with in-plane vector 2775 helper.CopyVector(candidate1->point->node); 2776 helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node); 2777 double phi = BaseLineVector.Angle(&helper); 2778 if (OrthogonalVector.ScalarProduct(&helper) > 0) { 2779 phi = 2.*M_PI - phi; 2780 } 2781 helper.CopyVector(candidate2->point->node); 2782 helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node); 2783 double psi = BaseLineVector.Angle(&helper); 2784 if (OrthogonalVector.ScalarProduct(&helper) > 0) { 2785 psi = 2.*M_PI - psi; 2786 } 2787 2788 cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl; 2789 cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl; 2790 2791 // return comparison 2792 return phi < psi; 2793 }; 2794 2795 /** 2796 * Finds the point which is second closest to the provided one. 2797 * 2798 * @param Point to which to find the second closest other point 2799 * @param linked cell structure 2800 * 2801 * @return point which is second closest to the provided one 2802 */ 2803 TesselPoint* FindSecondClosestPoint(const Vector* Point, LinkedCell* LC) 2804 { 2805 LinkedNodes *List = NULL; 2806 TesselPoint* closestPoint = NULL; 2807 TesselPoint* secondClosestPoint = NULL; 2808 double distance = 1e16; 2809 double secondDistance = 1e16; 2810 Vector helper; 2811 int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 2812 2813 LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly 2814 for(int i=0;i<NDIM;i++) // store indices of this cell 2815 N[i] = LC->n[i]; 2816 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl; 2817 2818 LC->GetNeighbourBounds(Nlower, Nupper); 2819 //cout << endl; 2820 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2821 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2822 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2823 List = LC->GetCurrentCell(); 2824 cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl; 2825 if (List != NULL) { 2826 for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2827 helper.CopyVector(Point); 2828 helper.SubtractVector((*Runner)->node); 2829 double currentNorm = helper. Norm(); 2830 if (currentNorm < distance) { 2831 // remember second point 2832 secondDistance = distance; 2833 secondClosestPoint = closestPoint; 2834 // mark down new closest point 2835 distance = currentNorm; 2836 closestPoint = (*Runner); 2837 cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl; 3077 2838 } 3078 } 3079 MiddleNode = EndNode; 3080 if (MiddleNode == connectedPath->end()) { 3081 cout << Verbose(1) << "CRITICAL: Could not find a smallest angle!" << endl; 3082 exit(255); 3083 } 3084 StartNode = MiddleNode; 3085 if (StartNode == connectedPath->begin()) 3086 StartNode = connectedPath->end(); 3087 StartNode--; 3088 EndNode++; 3089 if (EndNode == connectedPath->end()) 3090 EndNode = connectedPath->begin(); 3091 cout << Verbose(4) << "INFO: StartNode is " << **StartNode << "." << endl; 3092 cout << Verbose(4) << "INFO: MiddleNode is " << **MiddleNode << "." << endl; 3093 cout << Verbose(4) << "INFO: EndNode is " << **EndNode << "." << endl; 3094 *out << Verbose(3) << "INFO: Attempting to create triangle " << (*StartNode)->Name << ", " << (*MiddleNode)->Name << " and " << (*EndNode)->Name << "." << endl; 3095 TriangleCandidates[0] = *StartNode; 3096 TriangleCandidates[1] = *MiddleNode; 3097 TriangleCandidates[2] = *EndNode; 3098 triangle = GetPresentTriangle(out, TriangleCandidates); 3099 if (triangle != NULL) { 3100 cout << Verbose(1) << "WARNING: New triangle already present, skipping!" << endl; 3101 StartNode++; 3102 MiddleNode++; 3103 EndNode++; 3104 if (StartNode == connectedPath->end()) 3105 StartNode = connectedPath->begin(); 3106 if (MiddleNode == connectedPath->end()) 3107 MiddleNode = connectedPath->begin(); 3108 if (EndNode == connectedPath->end()) 3109 EndNode = connectedPath->begin(); 3110 continue; 3111 } 3112 *out << Verbose(5) << "Adding new triangle points."<< endl; 3113 AddTesselationPoint(*StartNode, 0); 3114 AddTesselationPoint(*MiddleNode, 1); 3115 AddTesselationPoint(*EndNode, 2); 3116 *out << Verbose(5) << "Adding new triangle lines."<< endl; 3117 AddTesselationLine(TPS[0], TPS[1], 0); 3118 AddTesselationLine(TPS[0], TPS[2], 1); 3119 NewLines.push_back(BLS[1]); 3120 AddTesselationLine(TPS[1], TPS[2], 2); 3121 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3122 BTS->GetNormalVector(NormalVector); 3123 AddTesselationTriangle(); 3124 // calculate volume summand as a general tetraeder 3125 volume += CalculateVolumeofGeneralTetraeder(TPS[0]->node->node, TPS[1]->node->node, TPS[2]->node->node, &OldPoint); 3126 // advance number 3127 count++; 3128 3129 // prepare nodes for next triangle 3130 StartNode = EndNode; 3131 cout << Verbose(4) << "Removing " << **MiddleNode << " from closed path, remaining points: " << connectedPath->size() << "." << endl; 3132 connectedPath->remove(*MiddleNode); // remove the middle node (it is surrounded by triangles) 3133 if (connectedPath->size() == 2) { // we are done 3134 connectedPath->remove(*StartNode); // remove the start node 3135 connectedPath->remove(*EndNode); // remove the end node 3136 break; 3137 } else if (connectedPath->size() < 2) { // something's gone wrong! 3138 cout << Verbose(1) << "CRITICAL: There are only two endpoints left!" << endl; 3139 exit(255); 2839 } 3140 2840 } else { 3141 MiddleNode = StartNode; 3142 MiddleNode++; 3143 if (MiddleNode == connectedPath->end()) 3144 MiddleNode = connectedPath->begin(); 3145 EndNode = MiddleNode; 3146 EndNode++; 3147 if (EndNode == connectedPath->end()) 3148 EndNode = connectedPath->begin(); 2841 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," 2842 << LC->n[2] << " is invalid!" << endl; 3149 2843 } 3150 2844 } 3151 // maximize the inner lines (we preferentially created lines with a huge angle, which is for the tesselation not wanted though useful for the closing) 3152 if (NewLines.size() > 1) { 3153 list<class BoundaryLineSet *>::iterator Candidate; 3154 class BoundaryLineSet *OtherBase = NULL; 3155 double tmp, maxgain; 3156 do { 3157 maxgain = 0; 3158 for(list<class BoundaryLineSet *>::iterator Runner = NewLines.begin(); Runner != NewLines.end(); Runner++) { 3159 tmp = PickFarthestofTwoBaselines(out, *Runner); 3160 if (maxgain < tmp) { 3161 maxgain = tmp; 3162 Candidate = Runner; 2845 2846 return secondClosestPoint; 2847 }; 2848 2849 /** 2850 * Finds the point which is closest to the provided one. 2851 * 2852 * @param Point to which to find the closest other point 2853 * @param SecondPoint the second closest other point on return, NULL if none found 2854 * @param linked cell structure 2855 * 2856 * @return point which is closest to the provided one, NULL if none found 2857 */ 2858 TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC) 2859 { 2860 LinkedNodes *List = NULL; 2861 TesselPoint* closestPoint = NULL; 2862 SecondPoint = NULL; 2863 double distance = 1e16; 2864 double secondDistance = 1e16; 2865 Vector helper; 2866 int N[NDIM], Nlower[NDIM], Nupper[NDIM]; 2867 2868 LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly 2869 for(int i=0;i<NDIM;i++) // store indices of this cell 2870 N[i] = LC->n[i]; 2871 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl; 2872 2873 LC->GetNeighbourBounds(Nlower, Nupper); 2874 //cout << endl; 2875 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++) 2876 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++) 2877 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) { 2878 List = LC->GetCurrentCell(); 2879 cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl; 2880 if (List != NULL) { 2881 for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) { 2882 helper.CopyVector(Point); 2883 helper.SubtractVector((*Runner)->node); 2884 double currentNorm = helper. Norm(); 2885 if (currentNorm < distance) { 2886 secondDistance = distance; 2887 SecondPoint = closestPoint; 2888 distance = currentNorm; 2889 closestPoint = (*Runner); 2890 cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl; 2891 } else if (currentNorm < secondDistance) { 2892 secondDistance = currentNorm; 2893 SecondPoint = (*Runner); 2894 cout << Verbose(2) << "INFO: New Second Nearest Neighbour is " << *SecondPoint << "." << endl; 3163 2895 } 3164 2896 } 3165 if (maxgain != 0) { 3166 volume += maxgain; 3167 cout << Verbose(3) << "Flipping baseline with highest volume" << **Candidate << "." << endl; 3168 OtherBase = FlipBaseline(out, *Candidate); 3169 NewLines.erase(Candidate); 3170 NewLines.push_back(OtherBase); 3171 } 3172 } while (maxgain != 0.); 2897 } else { 2898 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," 2899 << LC->n[2] << " is invalid!" << endl; 2900 } 3173 2901 } 3174 2902 3175 ListOfClosedPaths->remove(connectedPath); 3176 delete(connectedPath); 3177 } 3178 *out << Verbose(1) << count << " triangles were created." << endl; 3179 } else { 3180 while (!ListOfClosedPaths->empty()) { 3181 ListRunner = ListOfClosedPaths->begin(); 3182 connectedPath = *ListRunner; 3183 ListOfClosedPaths->remove(connectedPath); 3184 delete(connectedPath); 3185 } 3186 *out << Verbose(1) << "No need to create any triangles." << endl; 3187 } 3188 delete(ListOfClosedPaths); 3189 3190 *out << Verbose(1) << "Removed volume is " << volume << "." << endl; 3191 3192 return volume; 3193 }; 3194 3195 2903 return closestPoint; 2904 }; 3196 2905 3197 2906 /** … … 3230 2939 FindTriangle = FindLine->second->triangles.begin(); 3231 2940 for (; FindTriangle != FindLine->second->triangles.end(); FindTriangle++) { 3232 if (FindTriangle->second->IsPresentTupel(TrianglePoints)) { 2941 if (( 2942 (FindTriangle->second->endpoints[0] == TrianglePoints[0]) 2943 || (FindTriangle->second->endpoints[0] == TrianglePoints[1]) 2944 || (FindTriangle->second->endpoints[0] == TrianglePoints[2]) 2945 ) && ( 2946 (FindTriangle->second->endpoints[1] == TrianglePoints[0]) 2947 || (FindTriangle->second->endpoints[1] == TrianglePoints[1]) 2948 || (FindTriangle->second->endpoints[1] == TrianglePoints[2]) 2949 ) && ( 2950 (FindTriangle->second->endpoints[2] == TrianglePoints[0]) 2951 || (FindTriangle->second->endpoints[2] == TrianglePoints[1]) 2952 || (FindTriangle->second->endpoints[2] == TrianglePoints[2]) 2953 ) 2954 ) { 3233 2955 result->push_back(FindTriangle->second); 3234 2956 } … … 3248 2970 3249 2971 /** 3250 * Finds all degenerated lines within the tesselation structure.3251 *3252 * @return map of keys of degenerated line pairs, each line occurs twice3253 * in the list, once as key and once as value3254 */3255 map<int, int> * Tesselation::FindAllDegeneratedLines()3256 {3257 map<int, class BoundaryLineSet *> AllLines;3258 map<int, int> * DegeneratedLines = new map<int, int>;3259 3260 // sanity check3261 if (LinesOnBoundary.empty()) {3262 cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure.";3263 return DegeneratedLines;3264 }3265 3266 LineMap::iterator LineRunner1;3267 pair<LineMap::iterator, bool> tester;3268 for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) {3269 tester = AllLines.insert( pair<int,BoundaryLineSet *> (LineRunner1->second->endpoints[0]->Nr, LineRunner1->second) );3270 if ((!tester.second) && (tester.first->second->endpoints[1]->Nr == LineRunner1->second->endpoints[1]->Nr)) { // found degenerated line3271 DegeneratedLines->insert ( pair<int, int> (LineRunner1->second->Nr, tester.first->second->Nr) );3272 DegeneratedLines->insert ( pair<int, int> (tester.first->second->Nr, LineRunner1->second->Nr) );3273 }3274 }3275 3276 AllLines.clear();3277 3278 cout << Verbose(1) << "FindAllDegeneratedLines() found " << DegeneratedLines->size() << " lines." << endl;3279 map<int,int>::iterator it;3280 for (it = DegeneratedLines->begin(); it != DegeneratedLines->end(); it++)3281 cout << Verbose(2) << (*it).first << " => " << (*it).second << endl;3282 3283 return DegeneratedLines;3284 }3285 3286 /**3287 2972 * Finds all degenerated triangles within the tesselation structure. 3288 2973 * … … 3290 2975 * in the list, once as key and once as value 3291 2976 */ 3292 map<int, int> * Tesselation::FindAllDegeneratedTriangles() 3293 { 3294 map<int, int> * DegeneratedLines = FindAllDegeneratedLines(); 3295 map<int, int> * DegeneratedTriangles = new map<int, int>; 3296 3297 TriangleMap::iterator TriangleRunner1, TriangleRunner2; 3298 LineMap::iterator Liner; 3299 class BoundaryLineSet *line1 = NULL, *line2 = NULL; 3300 3301 for (map<int, int>::iterator LineRunner = DegeneratedLines->begin(); LineRunner != DegeneratedLines->end(); ++LineRunner) { 3302 // run over both lines' triangles 3303 Liner = LinesOnBoundary.find(LineRunner->first); 3304 if (Liner != LinesOnBoundary.end()) 3305 line1 = Liner->second; 3306 Liner = LinesOnBoundary.find(LineRunner->second); 3307 if (Liner != LinesOnBoundary.end()) 3308 line2 = Liner->second; 3309 for (TriangleRunner1 = line1->triangles.begin(); TriangleRunner1 != line1->triangles.end(); ++TriangleRunner1) { 3310 for (TriangleRunner2 = line2->triangles.begin(); TriangleRunner2 != line2->triangles.end(); ++TriangleRunner2) { 3311 if ((TriangleRunner1->second != TriangleRunner2->second) 3312 && (TriangleRunner1->second->IsPresentTupel(TriangleRunner2->second))) { 3313 DegeneratedTriangles->insert( pair<int, int> (TriangleRunner1->second->Nr, TriangleRunner2->second->Nr) ); 3314 DegeneratedTriangles->insert( pair<int, int> (TriangleRunner2->second->Nr, TriangleRunner1->second->Nr) ); 2977 map<int, int> Tesselation::FindAllDegeneratedTriangles() 2978 { 2979 map<int, int> DegeneratedTriangles; 2980 2981 // sanity check 2982 if (LinesOnBoundary.empty()) { 2983 cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure."; 2984 return DegeneratedTriangles; 2985 } 2986 2987 LineMap::iterator LineRunner1, LineRunner2; 2988 2989 for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) { 2990 for (LineRunner2 = LinesOnBoundary.begin(); LineRunner2 != LinesOnBoundary.end(); ++LineRunner2) { 2991 if ((LineRunner1->second != LineRunner2->second) 2992 && (LineRunner1->second->endpoints[0] == LineRunner2->second->endpoints[0]) 2993 && (LineRunner1->second->endpoints[1] == LineRunner2->second->endpoints[1]) 2994 ) { 2995 TriangleMap::iterator TriangleRunner1 = LineRunner1->second->triangles.begin(), 2996 TriangleRunner2 = LineRunner2->second->triangles.begin(); 2997 2998 for (; TriangleRunner1 != LineRunner1->second->triangles.end(); ++TriangleRunner1) { 2999 for (; TriangleRunner2 != LineRunner2->second->triangles.end(); ++TriangleRunner2) { 3000 if ((TriangleRunner1->second != TriangleRunner2->second) 3001 && (TriangleRunner1->second->endpoints[0] == TriangleRunner2->second->endpoints[0]) 3002 && (TriangleRunner1->second->endpoints[1] == TriangleRunner2->second->endpoints[1]) 3003 && (TriangleRunner1->second->endpoints[2] == TriangleRunner2->second->endpoints[2]) 3004 ) { 3005 DegeneratedTriangles[TriangleRunner1->second->Nr] = TriangleRunner2->second->Nr; 3006 DegeneratedTriangles[TriangleRunner2->second->Nr] = TriangleRunner1->second->Nr; 3007 } 3008 } 3315 3009 } 3316 3010 } 3317 3011 } 3318 3012 } 3319 delete(DegeneratedLines); 3320 3321 cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles->size() << " triangles:" << endl; 3013 3014 cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles.size() << " triangles." << endl; 3322 3015 map<int,int>::iterator it; 3323 for (it = DegeneratedTriangles ->begin(); it != DegeneratedTriangles->end(); it++)3016 for (it = DegeneratedTriangles.begin(); it != DegeneratedTriangles.end(); it++) 3324 3017 cout << Verbose(2) << (*it).first << " => " << (*it).second << endl; 3325 3018 … … 3333 3026 void Tesselation::RemoveDegeneratedTriangles() 3334 3027 { 3335 map<int, int> * DegeneratedTriangles = FindAllDegeneratedTriangles(); 3336 TriangleMap::iterator finder; 3337 BoundaryTriangleSet *triangle = NULL, *partnerTriangle = NULL; 3338 int count = 0; 3339 3340 cout << Verbose(1) << "Begin of RemoveDegeneratedTriangles" << endl; 3341 3342 for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles->begin(); 3343 TriangleKeyRunner != DegeneratedTriangles->end(); ++TriangleKeyRunner 3028 map<int, int> DegeneratedTriangles = FindAllDegeneratedTriangles(); 3029 3030 for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles.begin(); 3031 TriangleKeyRunner != DegeneratedTriangles.end(); ++TriangleKeyRunner 3344 3032 ) { 3345 finder = TrianglesOnBoundary.find(TriangleKeyRunner->first); 3346 if (finder != TrianglesOnBoundary.end()) 3347 triangle = finder->second; 3348 else 3349 break; 3350 finder = TrianglesOnBoundary.find(TriangleKeyRunner->second); 3351 if (finder != TrianglesOnBoundary.end()) 3352 partnerTriangle = finder->second; 3353 else 3354 break; 3033 BoundaryTriangleSet *triangle = TrianglesOnBoundary.find(TriangleKeyRunner->first)->second, 3034 *partnerTriangle = TrianglesOnBoundary.find(TriangleKeyRunner->second)->second; 3355 3035 3356 3036 bool trianglesShareLine = false; … … 3364 3044 && (triangle->endpoints[0]->LinesCount > 2) 3365 3045 ) { 3366 // check whether we have to fix lines3367 BoundaryTriangleSet *Othertriangle = NULL;3368 BoundaryTriangleSet *OtherpartnerTriangle = NULL;3369 TriangleMap::iterator TriangleRunner;3370 for (int i = 0; i < 3; ++i)3371 for (int j = 0; j < 3; ++j)3372 if (triangle->lines[i] != partnerTriangle->lines[j]) {3373 // get the other two triangles3374 for (TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); ++TriangleRunner)3375 if (TriangleRunner->second != triangle) {3376 Othertriangle = TriangleRunner->second;3377 }3378 for (TriangleRunner = partnerTriangle->lines[i]->triangles.begin(); TriangleRunner != partnerTriangle->lines[i]->triangles.end(); ++TriangleRunner)3379 if (TriangleRunner->second != partnerTriangle) {3380 OtherpartnerTriangle = TriangleRunner->second;3381 }3382 /// interchanges their lines so that triangle->lines[i] == partnerTriangle->lines[j]3383 // the line of triangle receives the degenerated ones3384 triangle->lines[i]->triangles.erase(Othertriangle->Nr);3385 triangle->lines[i]->triangles.insert( TrianglePair( partnerTriangle->Nr, partnerTriangle) );3386 for (int k=0;k<3;k++)3387 if (triangle->lines[i] == Othertriangle->lines[k]) {3388 Othertriangle->lines[k] = partnerTriangle->lines[j];3389 break;3390 }3391 // the line of partnerTriangle receives the non-degenerated ones3392 partnerTriangle->lines[j]->triangles.erase( partnerTriangle->Nr);3393 partnerTriangle->lines[j]->triangles.insert( TrianglePair( Othertriangle->Nr, Othertriangle) );3394 partnerTriangle->lines[j] = triangle->lines[i];3395 }3396 3397 // erase the pair3398 count += (int) DegeneratedTriangles->erase(triangle->Nr);3399 3046 cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *triangle << "." << endl; 3400 3047 RemoveTesselationTriangle(triangle); 3401 count += (int) DegeneratedTriangles->erase(partnerTriangle->Nr);3402 3048 cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *partnerTriangle << "." << endl; 3403 3049 RemoveTesselationTriangle(partnerTriangle); 3050 DegeneratedTriangles.erase(DegeneratedTriangles.find(partnerTriangle->Nr)); 3404 3051 } else { 3405 3052 cout << Verbose(1) << "RemoveDegeneratedTriangles() does not remove triangle " << *triangle … … 3408 3055 } 3409 3056 } 3410 delete(DegeneratedTriangles);3411 3412 cout << Verbose(1) << "RemoveDegeneratedTriangles() removed " << count << " triangles:" << endl;3413 cout << Verbose(1) << "End of RemoveDegeneratedTriangles" << endl;3414 3057 } 3415 3058 3416 /** Adds an outside Tesselpoint to the envelope via (two) degenerated triangles. 3417 * We look for the closest point on the boundary, we look through its connected boundary lines and 3418 * seek the one with the minimum angle between its center point and the new point and this base line. 3419 * We open up the line by adding a degenerated triangle, whose other side closes the base line again. 3420 * \param *out output stream for debugging 3421 * \param *point point to add 3422 * \param *LC Linked Cell structure to find nearest point 3423 */ 3424 void Tesselation::AddBoundaryPointByDegeneratedTriangle(ofstream *out, class TesselPoint *point, LinkedCell *LC) 3425 { 3426 *out << Verbose(2) << "Begin of AddBoundaryPointByDegeneratedTriangle" << endl; 3427 3428 // find nearest boundary point 3429 class TesselPoint *BackupPoint = NULL; 3430 class TesselPoint *NearestPoint = FindClosestPoint(point->node, BackupPoint, LC); 3431 class BoundaryPointSet *NearestBoundaryPoint = NULL; 3432 PointMap::iterator PointRunner; 3433 3434 if (NearestPoint == point) 3435 NearestPoint = BackupPoint; 3436 PointRunner = PointsOnBoundary.find(NearestPoint->nr); 3437 if (PointRunner != PointsOnBoundary.end()) { 3438 NearestBoundaryPoint = PointRunner->second; 3439 } else { 3440 *out << Verbose(1) << "ERROR: I cannot find the boundary point." << endl; 3441 return; 3442 } 3443 *out << Verbose(2) << "Nearest point on boundary is " << NearestPoint->Name << "." << endl; 3444 3445 // go through its lines and find the best one to split 3446 Vector CenterToPoint; 3447 Vector BaseLine; 3448 double angle, BestAngle = 0.; 3449 class BoundaryLineSet *BestLine = NULL; 3450 for (LineMap::iterator Runner = NearestBoundaryPoint->lines.begin(); Runner != NearestBoundaryPoint->lines.end(); Runner++) { 3451 BaseLine.CopyVector(Runner->second->endpoints[0]->node->node); 3452 BaseLine.SubtractVector(Runner->second->endpoints[1]->node->node); 3453 CenterToPoint.CopyVector(Runner->second->endpoints[0]->node->node); 3454 CenterToPoint.AddVector(Runner->second->endpoints[1]->node->node); 3455 CenterToPoint.Scale(0.5); 3456 CenterToPoint.SubtractVector(point->node); 3457 angle = CenterToPoint.Angle(&BaseLine); 3458 if (fabs(angle - M_PI/2.) < fabs(BestAngle - M_PI/2.)) { 3459 BestAngle = angle; 3460 BestLine = Runner->second; 3461 } 3462 } 3463 3464 // remove one triangle from the chosen line 3465 class BoundaryTriangleSet *TempTriangle = (BestLine->triangles.begin())->second; 3466 BestLine->triangles.erase(TempTriangle->Nr); 3467 int nr = -1; 3468 for (int i=0;i<3; i++) { 3469 if (TempTriangle->lines[i] == BestLine) { 3470 nr = i; 3471 break; 3472 } 3473 } 3474 3475 // create new triangle to connect point (connects automatically with the missing spot of the chosen line) 3476 *out << Verbose(5) << "Adding new triangle points."<< endl; 3477 AddTesselationPoint((BestLine->endpoints[0]->node), 0); 3478 AddTesselationPoint((BestLine->endpoints[1]->node), 1); 3479 AddTesselationPoint(point, 2); 3480 *out << Verbose(5) << "Adding new triangle lines."<< endl; 3481 AddTesselationLine(TPS[0], TPS[1], 0); 3482 AddTesselationLine(TPS[0], TPS[2], 1); 3483 AddTesselationLine(TPS[1], TPS[2], 2); 3484 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3485 BTS->GetNormalVector(TempTriangle->NormalVector); 3486 BTS->NormalVector.Scale(-1.); 3487 *out << Verbose(3) << "INFO: NormalVector of new triangle is " << BTS->NormalVector << "." << endl; 3488 AddTesselationTriangle(); 3489 3490 // create other side of this triangle and close both new sides of the first created triangle 3491 *out << Verbose(5) << "Adding new triangle points."<< endl; 3492 AddTesselationPoint((BestLine->endpoints[0]->node), 0); 3493 AddTesselationPoint((BestLine->endpoints[1]->node), 1); 3494 AddTesselationPoint(point, 2); 3495 *out << Verbose(5) << "Adding new triangle lines."<< endl; 3496 AddTesselationLine(TPS[0], TPS[1], 0); 3497 AddTesselationLine(TPS[0], TPS[2], 1); 3498 AddTesselationLine(TPS[1], TPS[2], 2); 3499 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3500 BTS->GetNormalVector(TempTriangle->NormalVector); 3501 *out << Verbose(3) << "INFO: NormalVector of other new triangle is " << BTS->NormalVector << "." << endl; 3502 AddTesselationTriangle(); 3503 3504 // add removed triangle to the last open line of the second triangle 3505 for (int i=0;i<3;i++) { // look for the same line as BestLine (only it's its degenerated companion) 3506 if ((BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[0])) && (BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[1]))) { 3507 if (BestLine == BTS->lines[i]){ 3508 *out << Verbose(1) << "CRITICAL: BestLine is same as found line, something's wrong here!" << endl; 3509 exit(255); 3510 } 3511 BTS->lines[i]->triangles.insert( pair<int, class BoundaryTriangleSet *> (TempTriangle->Nr, TempTriangle) ); 3512 TempTriangle->lines[nr] = BTS->lines[i]; 3513 break; 3514 } 3515 } 3516 3517 // exit 3518 *out << Verbose(2) << "End of AddBoundaryPointByDegeneratedTriangle" << endl; 3519 }; 3520 3521 /** Writes the envelope to file. 3522 * \param *out otuput stream for debugging 3523 * \param *filename basename of output file 3524 * \param *cloud PointCloud structure with all nodes 3525 */ 3526 void Tesselation::Output(ofstream *out, const char *filename, PointCloud *cloud) 3527 { 3528 ofstream *tempstream = NULL; 3529 string NameofTempFile; 3530 char NumberName[255]; 3531 3532 if (LastTriangle != NULL) { 3533 sprintf(NumberName, "-%04d-%s_%s_%s", (int)TrianglesOnBoundary.size(), LastTriangle->endpoints[0]->node->Name, LastTriangle->endpoints[1]->node->Name, LastTriangle->endpoints[2]->node->Name); 3534 if (DoTecplotOutput) { 3535 string NameofTempFile(filename); 3536 NameofTempFile.append(NumberName); 3537 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 3538 NameofTempFile.erase(npos, 1); 3539 NameofTempFile.append(TecplotSuffix); 3540 *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 3541 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 3542 WriteTecplotFile(out, tempstream, this, cloud, TriangleFilesWritten); 3543 tempstream->close(); 3544 tempstream->flush(); 3545 delete(tempstream); 3546 } 3547 3548 if (DoRaster3DOutput) { 3549 string NameofTempFile(filename); 3550 NameofTempFile.append(NumberName); 3551 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 3552 NameofTempFile.erase(npos, 1); 3553 NameofTempFile.append(Raster3DSuffix); 3554 *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 3555 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 3556 WriteRaster3dFile(out, tempstream, this, cloud); 3557 IncludeSphereinRaster3D(out, tempstream, this, cloud); 3558 tempstream->close(); 3559 tempstream->flush(); 3560 delete(tempstream); 3561 } 3562 } 3563 if (DoTecplotOutput || DoRaster3DOutput) 3564 TriangleFilesWritten++; 3565 }; 3059 /** Gets the angle between a point and a reference relative to the provided center. 3060 * We have two shanks point and reference between which the angle is calculated 3061 * and by scalar product with OrthogonalVector we decide the interval. 3062 * @param point to calculate the angle for 3063 * @param reference to which to calculate the angle 3064 * @param OrthogonalVector points in direction of [pi,2pi] interval 3065 * 3066 * @return angle between point and reference 3067 */ 3068 double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector) 3069 { 3070 if (reference.IsZero()) 3071 return M_PI; 3072 3073 // calculate both angles and correct with in-plane vector 3074 if (point.IsZero()) 3075 return M_PI; 3076 double phi = point.Angle(&reference); 3077 if (OrthogonalVector.ScalarProduct(&point) > 0) { 3078 phi = 2.*M_PI - phi; 3079 } 3080 3081 cout << Verbose(3) << "INFO: " << point << " has angle " << phi << " with respect to reference " << reference << "." << endl; 3082 3083 return phi; 3084 } 3085
Note:
See TracChangeset
for help on using the changeset viewer.