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