Changes in src/Tesselation/tesselation.cpp [8592c9:e2396e]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tesselation/tesselation.cpp
r8592c9 re2396e 35 35 #include "CodePatterns/MemDebug.hpp" 36 36 37 #include <algorithm> 38 #include <boost/foreach.hpp> 37 39 #include <fstream> 38 40 #include <iomanip> 41 #include <iterator> 39 42 #include <sstream> 40 43 … … 66 69 class molecule; 67 70 68 const char *TecplotSuffix =".dat";69 const char *Raster3DSuffix =".r3d";70 const char *VRMLSUffix =".wrl";71 72 const double ParallelEpsilon =1e-3;71 const char *TecplotSuffix = ".dat"; 72 const char *Raster3DSuffix = ".r3d"; 73 const char *VRMLSUffix = ".wrl"; 74 75 const double ParallelEpsilon = 1e-3; 73 76 const double Tesselation::HULLEPSILON = 1e-9; 74 77 … … 76 79 */ 77 80 Tesselation::Tesselation() : 78 PointsOnBoundaryCount(0), 79 LinesOnBoundaryCount(0), 80 TrianglesOnBoundaryCount(0), 81 LastTriangle(NULL), 82 TriangleFilesWritten(0), 83 InternalPointer(PointsOnBoundary.begin()) 81 PointsOnBoundaryCount(0), LinesOnBoundaryCount(0), TrianglesOnBoundaryCount(0), LastTriangle(NULL), TriangleFilesWritten(0), InternalPointer(PointsOnBoundary.begin()) 84 82 { 85 83 //Info FunctionInfo(__func__); … … 113 111 { 114 112 // create linkedcell 115 LinkedCell_deprecated *LinkedList = new LinkedCell_deprecated(cloud, 2.*SPHERERADIUS);116 117 118 119 120 121 for (size_t i =0;i<3;++i, cloud.GoToNext())113 LinkedCell_deprecated *LinkedList = new LinkedCell_deprecated(cloud, 2. * SPHERERADIUS); 114 115 // check for at least three points 116 { 117 bool ThreePointsFound = true; 118 cloud.GoToFirst(); 119 for (size_t i = 0; i < 3; ++i, cloud.GoToNext()) 122 120 ThreePointsFound &= (!cloud.IsEnd()); 123 121 cloud.GoToFirst(); … … 126 124 return; 127 125 } 128 129 130 126 } 127 128 // find a starting triangle 131 129 FindStartingTriangle(SPHERERADIUS, LinkedList); 132 130 … … 142 140 //the line is there, so there is a triangle, but only one. 143 141 const bool TesselationFailFlag = FindNextSuitableTriangle(*baseline, *T, SPHERERADIUS, LinkedList); 144 ASSERT( TesselationFailFlag, 145 "Tesselation::operator() - no suitable candidate triangle found."); 142 ASSERT(TesselationFailFlag, "Tesselation::operator() - no suitable candidate triangle found."); 146 143 } 147 144 } 148 145 149 146 // 2b. search for smallest ShortestAngle among all candidates 150 double ShortestAngle = 4. *M_PI;147 double ShortestAngle = 4. * M_PI; 151 148 for (CandidateMap::iterator Runner = OpenLines.begin(); Runner != OpenLines.end(); Runner++) { 152 149 if (Runner->second->ShortestAngle < ShortestAngle) { … … 155 152 } 156 153 } 157 if ((ShortestAngle == 4. *M_PI) || (baseline->pointlist.empty()))154 if ((ShortestAngle == 4. * M_PI) || (baseline->pointlist.empty())) 158 155 OneLoopWithoutSuccessFlag = false; 159 156 else { … … 161 158 } 162 159 } 160 161 delete LinkedList; 163 162 } 164 163 … … 170 169 double Tesselation::getVolumeOfConvexEnvelope(const bool IsAngstroem) const 171 170 { 171 // calculate center of gravity 172 Vector center; 173 if (!PointsOnBoundary.empty()) { 174 for (PointMap::const_iterator iter = PointsOnBoundary.begin(); 175 iter != PointsOnBoundary.end(); ++iter) 176 center += iter->second->node->getPosition(); 177 center *= 1./(double)PointsOnBoundary.size(); 178 } 179 180 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 172 181 double volume = 0.; 173 Vector x; 174 Vector y; 175 176 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 177 for (TriangleMap::const_iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) 178 { // go through every triangle, calculate volume of its pyramid with CoG as peak 179 x = runner->second->getEndpoint(0) - runner->second->getEndpoint(1); 180 const double G = runner->second->getArea(); 181 x = runner->second->getPlane().getNormal(); 182 x.Scale(runner->second->getEndpoint(1).ScalarProduct(x)); 183 const double h = x.Norm(); // distance of CoG to triangle 184 const double PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 185 LOG(1, "INFO: Area of triangle is " << setprecision(10) << G << " " 186 << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " 187 << h << " and the volume is " << PyramidVolume << " " 188 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."); 189 volume += PyramidVolume; 190 } 191 LOG(0, "RESULT: The summed volume is " << setprecision(6) 192 << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."); 182 for (TriangleMap::const_iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { // go through every triangle, calculate volume of its pyramid with CoG as peak 183 const double TetrahedronVolume = CalculateVolumeofGeneralTetraeder( 184 runner->second->endpoints[0]->getPosition(), 185 runner->second->endpoints[1]->getPosition(), 186 runner->second->endpoints[2]->getPosition(), 187 center); 188 LOG(1, "INFO: volume of tetrahedron is " << setprecision(10) << TetrahedronVolume 189 << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."); 190 volume += TetrahedronVolume; 191 } 192 LOG(0, "RESULT: The summed volume is " << setprecision(6) << volume 193 << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."); 193 194 194 195 return volume; … … 207 208 208 209 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 209 for (TriangleMap::const_iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) 210 { // go through every triangle, calculate volume of its pyramid with CoG as peak 211 const double area = runner->second->getArea(); 212 LOG(1, "INFO: Area of triangle is " << setprecision(10) << area << " " 213 << (IsAngstroem ? "angstrom" : "atomiclength") << "^2."); 214 surfacearea += area; 215 } 216 LOG(0, "RESULT: The summed surface area is " << setprecision(6) 217 << surfacearea << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."); 210 for (TriangleMap::const_iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { // go through every triangle, calculate volume of its pyramid with CoG as peak 211 const double area = runner->second->getArea(); 212 LOG(1, "INFO: Area of triangle is " << setprecision(10) << area << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^2."); 213 surfacearea += area; 214 } 215 LOG(0, "RESULT: The summed surface area is " << setprecision(6) << surfacearea << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."); 218 216 219 217 return surfacearea; 220 218 } 221 222 219 223 220 /** Gueses first starting triangle of the convex envelope. … … 251 248 tmp = B->second->node->DistanceSquared(C->second->node->getPosition()); 252 249 distance += tmp * tmp; 253 DistanceMMap.insert(DistanceMultiMapPair(distance, pair<PointMap::iterator, PointMap::iterator> 250 DistanceMMap.insert(DistanceMultiMapPair(distance, pair<PointMap::iterator, PointMap::iterator>(B, C))); 254 251 } 255 252 } … … 271 268 // 2. next, we have to check whether all points reside on only one side of the triangle 272 269 // 3. construct plane vector 273 PlaneVector = Plane(A->second->node->getPosition(), 274 baseline->second.first->second->node->getPosition(), 275 baseline->second.second->second->node->getPosition()).getNormal(); 270 PlaneVector = Plane(A->second->node->getPosition(), baseline->second.first->second->node->getPosition(), baseline->second.second->second->node->getPosition()).getNormal(); 276 271 LOG(2, "Plane vector of candidate triangle is " << PlaneVector); 277 272 // 4. loop over all points … … 388 383 // prepare some auxiliary vectors 389 384 Vector BaseLineCenter, BaseLine; 390 BaseLineCenter = 0.5 * ((baseline->second->endpoints[0]->node->getPosition()) + 391 (baseline->second->endpoints[1]->node->getPosition())); 385 BaseLineCenter = 0.5 * ((baseline->second->endpoints[0]->node->getPosition()) + (baseline->second->endpoints[1]->node->getPosition())); 392 386 BaseLine = (baseline->second->endpoints[0]->node->getPosition()) - (baseline->second->endpoints[1]->node->getPosition()); 393 387 … … 407 401 // vector in propagation direction (out of triangle) 408 402 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 409 PropagationVector = Plane(BaseLine, NormalVector, 0).getNormal();403 PropagationVector = Plane(BaseLine, NormalVector, 0).getNormal(); 410 404 TempVector = CenterVector - (baseline->second->endpoints[0]->node->getPosition()); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 411 405 //LOG(0, "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "."); … … 460 454 // in case NOT both were found, create virtually this triangle, get its normal vector, calculate angle 461 455 flag = true; 462 VirtualNormalVector = Plane((baseline->second->endpoints[0]->node->getPosition()), 463 (baseline->second->endpoints[1]->node->getPosition()), 464 (target->second->node->getPosition())).getNormal(); 465 TempVector = (1./3.) * ((baseline->second->endpoints[0]->node->getPosition()) + 466 (baseline->second->endpoints[1]->node->getPosition()) + 467 (target->second->node->getPosition())); 456 VirtualNormalVector = Plane((baseline->second->endpoints[0]->node->getPosition()), (baseline->second->endpoints[1]->node->getPosition()), (target->second->node->getPosition())).getNormal(); 457 TempVector = (1. / 3.) * ((baseline->second->endpoints[0]->node->getPosition()) + (baseline->second->endpoints[1]->node->getPosition()) + (target->second->node->getPosition())); 468 458 TempVector -= (*Center); 469 459 // make it always point outward … … 477 467 winner = target; 478 468 LOG(5, "DEBUG: New winner " << *winner->second->node << " due to smaller angle between normal vectors."); 479 } else if (fabs(SmallestAngle - TempAngle) < MYEPSILON) { // check the angle to propagation, both possible targets are in one plane! (their normals have same angle) 480 // hence, check the angles to some normal direction from our base line but in this common plane of both targets... 481 helper = (target->second->node->getPosition()) - BaseLineCenter; 482 helper.ProjectOntoPlane(BaseLine); 483 // ...the one with the smaller angle is the better candidate 484 TempVector = (target->second->node->getPosition()) - BaseLineCenter; 485 TempVector.ProjectOntoPlane(VirtualNormalVector); 486 TempAngle = TempVector.Angle(helper); 487 TempVector = (winner->second->node->getPosition()) - BaseLineCenter; 488 TempVector.ProjectOntoPlane(VirtualNormalVector); 489 if (TempAngle < TempVector.Angle(helper)) { 490 TempAngle = NormalVector.Angle(VirtualNormalVector); 491 SmallestAngle = TempAngle; 492 winner = target; 493 LOG(5, "DEBUG: New winner " << *winner->second->node << " due to smaller angle " << TempAngle << " to propagation direction."); 469 } else 470 if (fabs(SmallestAngle - TempAngle) < MYEPSILON) { // check the angle to propagation, both possible targets are in one plane! (their normals have same angle) 471 // hence, check the angles to some normal direction from our base line but in this common plane of both targets... 472 helper = (target->second->node->getPosition()) - BaseLineCenter; 473 helper.ProjectOntoPlane(BaseLine); 474 // ...the one with the smaller angle is the better candidate 475 TempVector = (target->second->node->getPosition()) - BaseLineCenter; 476 TempVector.ProjectOntoPlane(VirtualNormalVector); 477 TempAngle = TempVector.Angle(helper); 478 TempVector = (winner->second->node->getPosition()) - BaseLineCenter; 479 TempVector.ProjectOntoPlane(VirtualNormalVector); 480 if (TempAngle < TempVector.Angle(helper)) { 481 TempAngle = NormalVector.Angle(VirtualNormalVector); 482 SmallestAngle = TempAngle; 483 winner = target; 484 LOG(5, "DEBUG: New winner " << *winner->second->node << " due to smaller angle " << TempAngle << " to propagation direction."); 485 } else 486 LOG(5, "DEBUG: Keeping old winner " << *winner->second->node << " due to smaller angle to propagation direction."); 494 487 } else 495 LOG(5, "DEBUG: Keeping old winner " << *winner->second->node << " due to smaller angle to propagation direction."); 496 } else 497 LOG(5, "DEBUG: Keeping old winner " << *winner->second->node << " due to smaller angle between normal vectors."); 488 LOG(5, "DEBUG: Keeping old winner " << *winner->second->node << " due to smaller angle between normal vectors."); 498 489 } 499 490 } // end of loop over all boundary points … … 562 553 563 554 cloud.GoToFirst(); 564 PointCloudAdaptor< 555 PointCloudAdaptor<Tesselation, MapValueIterator<Tesselation::iterator> > newcloud(this, cloud.GetName()); 565 556 BoundaryPoints = new LinkedCell_deprecated(newcloud, 5.); 566 557 while (!cloud.IsEnd()) { // we only have to go once through all points, as boundary can become only bigger … … 729 720 * @param *b second endpoint 730 721 * @param n index of Tesselation::BLS giving the line with both endpoints 731 */ 732 void Tesselation::AddTesselationLine(const Vector * const OptCenter, const BoundaryPointSet * const candidate, class BoundaryPointSet *a, class BoundaryPointSet *b, const int n) 722 * @return true - inserted a new line, false - present line used 723 */ 724 bool Tesselation::AddTesselationLine(const Vector * const OptCenter, const BoundaryPointSet * const candidate, class BoundaryPointSet *a, class BoundaryPointSet *b, const int n) 733 725 { 734 726 bool insertNewLine = true; … … 746 738 if (FindLine->second->triangles.size() == 1) { 747 739 CandidateMap::iterator Finder = OpenLines.find(FindLine->second); 748 if (!Finder->second->pointlist.empty()) 749 LOG(4, "DEBUG: line " << *(FindLine->second) << " is open with candidate " << **(Finder->second->pointlist.begin()) << "."); 750 else 751 LOG(4, "DEBUG: line " << *(FindLine->second) << " is open with no candidate."); 752 // get open line 753 for (TesselPointList::const_iterator CandidateChecker = Finder->second->pointlist.begin(); CandidateChecker != Finder->second->pointlist.end(); ++CandidateChecker) { 754 if ((*(CandidateChecker) == candidate->node) && (OptCenter == NULL || OptCenter->DistanceSquared(Finder->second->OptCenter) < MYEPSILON )) { // stop searching if candidate matches 755 LOG(4, "ACCEPT: Candidate " << *(*CandidateChecker) << " has the right center " << Finder->second->OptCenter << "."); 740 ASSERT(Finder != OpenLines.end(), "Tesselation::AddTesselationLine() - " + toString(*FindLine->second) + " is not a new line and not in OpenLines."); 741 if (Finder->second != NULL) { 742 if (!Finder->second->pointlist.empty()) 743 LOG(4, "DEBUG: line " << *(FindLine->second) << " is open with candidate " << **(Finder->second->pointlist.begin()) << "."); 744 else { 745 LOG(4, "ACCEPT: line " << *(FindLine->second) << " is open with no candidate."); 756 746 insertNewLine = false; 757 747 WinningLine = FindLine->second; 758 break;759 } else {760 LOG(5, "REJECT: Candidate " << *(*CandidateChecker) << "'s center " << Finder->second->OptCenter << " does not match desired on " << *OptCenter << ".");761 748 } 749 // get open line 750 for (TesselPointList::const_iterator CandidateChecker = Finder->second->pointlist.begin(); CandidateChecker != Finder->second->pointlist.end(); ++CandidateChecker) { 751 if ((*(CandidateChecker) == candidate->node) && (OptCenter == NULL || OptCenter->DistanceSquared(Finder->second->OptCenter) < MYEPSILON)) { // stop searching if candidate matches 752 LOG(4, "ACCEPT: Candidate " << *(*CandidateChecker) << " has the right center " << Finder->second->OptCenter << "."); 753 insertNewLine = false; 754 WinningLine = FindLine->second; 755 break; 756 } else { 757 LOG(5, "REJECT: Candidate " << *(*CandidateChecker) << "'s center " << Finder->second->OptCenter << " does not match desired on " << *OptCenter << "."); 758 } 759 } 760 } else { 761 LOG(4, "ACCEPT: There are no candidates for present open line, use what we have."); 762 insertNewLine = false; 763 WinningLine = FindLine->second; 762 764 } 763 765 } … … 770 772 AddExistingTesselationTriangleLine(WinningLine, n); 771 773 } 774 775 return insertNewLine; 772 776 } 773 777 ; … … 794 798 // also add to open lines 795 799 CandidateForTesselation *CFT = new CandidateForTesselation(BLS[n]); 796 OpenLines.insert(pair<BoundaryLineSet *, CandidateForTesselation *> 800 OpenLines.insert(pair<BoundaryLineSet *, CandidateForTesselation *>(BLS[n], CFT)); 797 801 } 798 802 ; … … 883 887 } else { 884 888 output << "still attached to another triangle: "; 885 OpenLines.insert(pair<BoundaryLineSet *, CandidateForTesselation *> (triangle->lines[i], NULL));886 889 for (TriangleMap::iterator TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); TriangleRunner++) 887 890 output << "\t[" << (TriangleRunner->second)->Nr << "|" << *((TriangleRunner->second)->endpoints[0]) << ", " << *((TriangleRunner->second)->endpoints[1]) << ", " << *((TriangleRunner->second)->endpoints[2]) << "] \t"; 891 OpenLines.insert(pair<BoundaryLineSet *, CandidateForTesselation *>(triangle->lines[i], NULL)); 888 892 } 889 893 LOG(3, "DEBUG: " << output.str()); … … 919 923 else 920 924 Numbers[1] = -1; 925 926 // erase from OpenLines if present 927 { 928 CandidateMap::iterator openlineiter = OpenLines.find(line); 929 if (openlineiter != OpenLines.end()) 930 OpenLines.erase(openlineiter); 931 } 921 932 922 933 for (int i = 0; i < 2; i++) { … … 937 948 LOG(4, "DEBUG: " << *line->endpoints[i] << " has no more lines it's attached to, erasing."); 938 949 RemoveTesselationPoint(line->endpoints[i]); 939 } else if (DoLog(0)) { 940 std::stringstream output; 941 output << "DEBUG: " << *line->endpoints[i] << " has still lines it's attached to: "; 942 for (LineMap::iterator LineRunner = line->endpoints[i]->lines.begin(); LineRunner != line->endpoints[i]->lines.end(); LineRunner++) 943 output << "[" << *(LineRunner->second) << "] \t"; 944 LOG(4, output.str()); 945 } 950 } else 951 if (DoLog(0)) { 952 std::stringstream output; 953 output << "DEBUG: " << *line->endpoints[i] << " has still lines it's attached to: "; 954 for (LineMap::iterator LineRunner = line->endpoints[i]->lines.begin(); LineRunner != line->endpoints[i]->lines.end(); LineRunner++) 955 output << "[" << *(LineRunner->second) << "] \t"; 956 LOG(4, output.str()); 957 } 946 958 line->endpoints[i] = NULL; // free'd or not: disconnect 947 959 } else … … 985 997 //Info FunctionInfo(__func__); 986 998 987 LOG(3, "DEBUG: Checking whether sphere contains no others points ...");999 LOG(3, "DEBUG: Checking degeneracy by whether sphere contains no others points ..."); 988 1000 bool flag = true; 989 1001 … … 992 1004 TesselPointList *ListofPoints = LC->GetPointsInsideSphere(RADIUS, &CandidateLine.OtherOptCenter); 993 1005 994 LOG(3, "DEBUG: The following atoms are inside sphere at " << CandidateLine.OtherOptCenter << ":"); 1006 LOG(3, "DEBUG: CheckDegeneracy: There are " << ListofPoints->size() << " points inside the sphere."); 1007 LOG(4, "DEBUG: The following atoms are inside sphere at " << CandidateLine.OtherOptCenter << ":"); 995 1008 for (TesselPointList::const_iterator Runner = ListofPoints->begin(); Runner != ListofPoints->end(); ++Runner) 996 LOG( 3, "DEBUG: " << *(*Runner) << " with distance " << (*Runner)->distance(CandidateLine.OtherOptCenter) << ".");1009 LOG(4, "DEBUG: " << *(*Runner) << " with distance " << (*Runner)->distance(CandidateLine.OtherOptCenter) << "."); 997 1010 998 1011 // remove triangles's endpoints … … 1008 1021 LOG(3, "DEBUG: CheckDegeneracy: There are still " << ListofPoints->size() << " points inside the sphere."); 1009 1022 flag = false; 1010 LOG( 3, "DEBUG: External atoms inside of sphere at " << CandidateLine.OtherOptCenter << ":");1023 LOG(4, "DEBUG: External atoms inside of sphere at " << CandidateLine.OtherOptCenter << ":"); 1011 1024 for (TesselPointList::const_iterator Runner = ListofPoints->begin(); Runner != ListofPoints->end(); ++Runner) 1012 LOG( 3, "DEBUG: " << *(*Runner) << " with distance " << (*Runner)->distance(CandidateLine.OtherOptCenter) << ".");1013 } 1014 delete (ListofPoints);1025 LOG(4, "DEBUG: " << *(*Runner) << " with distance " << (*Runner)->distance(CandidateLine.OtherOptCenter) << "."); 1026 } 1027 delete ListofPoints; 1015 1028 1016 1029 return flag; … … 1155 1168 1156 1169 // 1. searching topmost point with respect to each axis 1170 LOG(2, "INFO: Searching for topmost pointer from each axis."); 1157 1171 for (int i = 0; i < NDIM; i++) { // each axis 1158 1172 LC->n[i] = LC->N[i] - 1; // current axis is topmost cell … … 1176 1190 } 1177 1191 1178 if (DoLog( 1)) {1192 if (DoLog(3)) { 1179 1193 std::stringstream output; 1180 1194 output << "Found maximum coordinates: "; … … 1190 1204 BaseLine = new BoundaryLineSet(); 1191 1205 BaseLine->endpoints[0] = new BoundaryPointSet(MaxPoint[k]); 1192 LOG(2, " DEBUG: Coordinates of start node at " << *BaseLine->endpoints[0]->node << ".");1206 LOG(2, "INFO: Coordinates of start node at " << *BaseLine->endpoints[0]->node << "."); 1193 1207 1194 1208 double ShortestAngle; … … 1203 1217 } 1204 1218 BaseLine->endpoints[1] = new BoundaryPointSet(Temporary); 1205 LOG( 1, "INFO: Second node is at " << *Temporary << ".");1219 LOG(2, "INFO: Second node is at " << *Temporary << "."); 1206 1220 1207 1221 // construct center of circle 1208 1222 CircleCenter = 0.5 * ((BaseLine->endpoints[0]->node->getPosition()) + (BaseLine->endpoints[1]->node->getPosition())); 1209 LOG( 1, "INFO: CircleCenter is at " << CircleCenter << ".");1223 LOG(4, "DEBUG: CircleCenter is at " << CircleCenter << "."); 1210 1224 1211 1225 // construct normal vector of circle 1212 1226 CirclePlaneNormal = (BaseLine->endpoints[0]->node->getPosition()) - (BaseLine->endpoints[1]->node->getPosition()); 1213 LOG( 1, "INFO: CirclePlaneNormal is at " << CirclePlaneNormal << ".");1227 LOG(4, "DEBUG: CirclePlaneNormal is at " << CirclePlaneNormal << "."); 1214 1228 1215 1229 double radius = CirclePlaneNormal.NormSquared(); … … 1218 1232 NormalVector.ProjectOntoPlane(CirclePlaneNormal); 1219 1233 NormalVector.Normalize(); 1220 LOG( 1, "INFO: NormalVector is at " << NormalVector << ".");1234 LOG(4, "DEBUG: NormalVector is at " << NormalVector << "."); 1221 1235 ShortestAngle = 2. * M_PI; // This will indicate the quadrant. 1222 1236 1223 SphereCenter = (CircleRadius * NormalVector) + 1237 SphereCenter = (CircleRadius * NormalVector) + CircleCenter; 1224 1238 // Now, NormalVector and SphereCenter are two orthonormalized vectors in the plane defined by CirclePlaneNormal (not normalized) 1225 1239 1226 1240 // look in one direction of baseline for initial candidate 1227 1241 try { 1228 SearchDirection = Plane(CirclePlaneNormal, NormalVector,0).getNormal(); // whether we look "left" first or "right" first is not important ... 1229 } catch(LinearAlgebraException) { 1230 ELOG(1, "Vectors are linear dependent: " 1231 << CirclePlaneNormal << ", " << NormalVector << "."); 1242 SearchDirection = Plane(CirclePlaneNormal, NormalVector, 0).getNormal(); // whether we look "left" first or "right" first is not important ... 1243 } catch (LinearAlgebraException &e) { 1244 ELOG(1, "Vectors are linear dependent: " << CirclePlaneNormal << ", " << NormalVector << "."); 1232 1245 delete BaseLine; 1233 1246 continue; … … 1235 1248 1236 1249 // adding point 1 and point 2 and add the line between them 1237 LOG( 2, "DEBUG: Found second point is at " << *BaseLine->endpoints[1]->node << ".");1250 LOG(3, "DEBUG: Found second point is at " << *BaseLine->endpoints[1]->node << "."); 1238 1251 1239 1252 //LOG(1, "INFO: OldSphereCenter is at " << helper << "."); … … 1244 1257 for (TesselPointList::iterator it = OptCandidates.pointlist.begin(); it != OptCandidates.pointlist.end(); it++) 1245 1258 output << *(*it); 1246 LOG( 2, "DEBUG: List of third Points is: " << output.str());1259 LOG(3, "DEBUG: List of third Points is: " << output.str()); 1247 1260 } 1248 1261 if (!OptCandidates.pointlist.empty()) { … … 1406 1419 // return result; 1407 1420 //}; 1408 1409 1421 /** This function finds a triangle to a line, adjacent to an existing one. 1410 1422 * @param out output stream for debugging … … 1438 1450 1439 1451 // construct center of circle 1440 CircleCenter = 0.5 * ((CandidateLine.BaseLine->endpoints[0]->node->getPosition()) + 1441 (CandidateLine.BaseLine->endpoints[1]->node->getPosition())); 1452 CircleCenter = 0.5 * ((CandidateLine.BaseLine->endpoints[0]->node->getPosition()) + (CandidateLine.BaseLine->endpoints[1]->node->getPosition())); 1442 1453 1443 1454 // construct normal vector of circle 1444 CirclePlaneNormal = (CandidateLine.BaseLine->endpoints[0]->node->getPosition()) - 1445 (CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 1455 CirclePlaneNormal = (CandidateLine.BaseLine->endpoints[0]->node->getPosition()) - (CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 1446 1456 1447 1457 // calculate squared radius of circle … … 1453 1463 CircleRadius = RADIUS * RADIUS - radius / 4.; 1454 1464 CirclePlaneNormal.Normalize(); 1455 LOG( 3, "DEBUG: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << ".");1456 1457 LOG( 3, "DEBUG: OldSphereCenter is at " << T.SphereCenter << ".");1465 LOG(4, "DEBUG: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "."); 1466 1467 LOG(4, "DEBUG: OldSphereCenter is at " << T.SphereCenter << "."); 1458 1468 1459 1469 // construct SearchDirection and an "outward pointer" 1460 SearchDirection = Plane(RelativeSphereCenter, CirclePlaneNormal, 0).getNormal();1470 SearchDirection = Plane(RelativeSphereCenter, CirclePlaneNormal, 0).getNormal(); 1461 1471 helper = CircleCenter - (ThirdPoint->node->getPosition()); 1462 if (helper.ScalarProduct(SearchDirection) < -HULLEPSILON) // ohoh, SearchDirection points inwards!1472 if (helper.ScalarProduct(SearchDirection) < -HULLEPSILON) // ohoh, SearchDirection points inwards! 1463 1473 SearchDirection.Scale(-1.); 1464 LOG( 3, "DEBUG: SearchDirection is " << SearchDirection << ".");1474 LOG(4, "DEBUG: SearchDirection is " << SearchDirection << "."); 1465 1475 if (fabs(RelativeSphereCenter.ScalarProduct(SearchDirection)) > HULLEPSILON) { 1466 1476 // rotated the wrong way! … … 1472 1482 1473 1483 } else { 1474 LOG( 3, "DEBUG: Circumcircle for base line " << *CandidateLine.BaseLine << " and base triangle " << T << " is too big!");1484 LOG(4, "DEBUG: Circumcircle for base line " << *CandidateLine.BaseLine << " and base triangle " << T << " is too big!"); 1475 1485 } 1476 1486 … … 1505 1515 baseline = Runner->second; 1506 1516 if (baseline->pointlist.empty()) { 1507 ASSERT((baseline->BaseLine->triangles.size() == 1), "Open line without exactly one attached triangle");1517 ASSERT((baseline->BaseLine->triangles.size() == 1), "Open line without exactly one attached triangle"); 1508 1518 T = (((baseline->BaseLine->triangles.begin()))->second); 1509 1519 LOG(4, "DEBUG: Finding best candidate for open line " << *baseline->BaseLine << " of triangle " << *T); … … 1538 1548 TesselPointList *connectedClosestPoints = GetCircleOfSetOfPoints(&SetOfNeighbours, TurningPoint, CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 1539 1549 1540 {1550 if (DoLog(3)) { 1541 1551 std::stringstream output; 1542 1552 for (TesselPointList::iterator TesselRunner = connectedClosestPoints->begin(); TesselRunner != connectedClosestPoints->end(); ++TesselRunner) 1543 1553 output << **TesselRunner; 1544 LOG(3, "DEBUG: List of Candidates for Turning Point " << *TurningPoint << ":" );1554 LOG(3, "DEBUG: List of Candidates for Turning Point " << *TurningPoint << ":" << output.str()); 1545 1555 } 1546 1556 … … 1583 1593 } 1584 1594 delete (connectedClosestPoints); 1585 }; 1595 } 1596 ; 1586 1597 1587 1598 /** for polygons (multiple candidates for a baseline) sets internal edges to the correct next candidate. … … 1603 1614 else { 1604 1615 LOG(4, "DEBUG: line " << *(FindLine->second) << " is open with no candidate, setting to next Sprinter" << (*Sprinter)); 1605 Finder->second->T = BTS; 1616 Finder->second->T = BTS; // is last triangle 1606 1617 Finder->second->pointlist.push_back(Sprinter); 1607 1618 Finder->second->ShortestAngle = 0.; … … 1610 1621 } 1611 1622 } 1612 }; 1623 } 1624 ; 1613 1625 1614 1626 /** If a given \a *triangle is degenerated, this adds both sides. … … 1646 1658 // give some verbose output about the whole procedure 1647 1659 if (CandidateLine.T != NULL) 1648 LOG(2, " DEBUG: --> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << ", from " << *CandidateLine.T << " and angle " << CandidateLine.ShortestAngle << ".");1660 LOG(2, "INFO: --> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << ", from " << *CandidateLine.T << " and angle " << CandidateLine.ShortestAngle << "."); 1649 1661 else 1650 LOG(2, " DEBUG: --> New starting triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " and no top triangle.");1662 LOG(2, "INFO: --> New starting triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " and no top triangle."); 1651 1663 triangle = BTS; 1652 1664 … … 1732 1744 ; 1733 1745 1746 bool Tesselation::isConvex() const 1747 { 1748 bool status = true; 1749 // go through all lines on boundary 1750 for (LineMap::const_iterator lineiter = LinesOnBoundary.begin(); 1751 lineiter != LinesOnBoundary.end(); ++lineiter) { 1752 if (!lineiter->second->CheckConvexityCriterion()) { 1753 LOG(2, "DEBUG: Line " << *lineiter->second << " is not convex."); 1754 status = false; 1755 } 1756 } 1757 return status; 1758 } 1759 1734 1760 /** Checks whether the quadragon of the two triangles connect to \a *Base is convex. 1735 1761 * We look whether the closest point on \a *Base with respect to the other baseline is outside … … 1868 1894 } 1869 1895 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { 1870 LOG(4, "DEBUG: Adding NormalVector " << runner->second->NormalVector << " of triangle " << *(runner->second) << ".");1896 LOG(4, "DEBUG: Adding NormalVector " << runner->second->NormalVector << " of triangle " << *(runner->second) << "."); 1871 1897 BaseLineNormal += (runner->second->NormalVector); 1872 1898 } … … 1897 1923 class BoundaryLineSet *OldLines[4], *NewLine; 1898 1924 class BoundaryPointSet *OldPoints[2]; 1899 Vector BaseLineNormal; 1925 Vector BaseLineNormal[2]; 1926 Vector OtherEndpoint[2]; // fourth point to either triangle 1900 1927 int OldTriangleNrs[2], OldBaseLineNr; 1901 1928 int i, m; 1902 1929 1903 1930 // calculate NormalVector for later use 1904 BaseLineNormal.Zero();1905 1931 if (Base->triangles.size() < 2) { 1906 1932 ELOG(1, "Less than two triangles are attached to this baseline!"); 1907 1933 return NULL; 1908 1934 } 1909 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { 1910 LOG(1, "INFO: Adding NormalVector " << runner->second->NormalVector << " of triangle " << *(runner->second) << "."); 1911 BaseLineNormal += (runner->second->NormalVector); 1912 } 1913 BaseLineNormal.Scale(-1. / 2.); // has to point inside for BoundaryTriangleSet::GetNormalVector() 1935 { 1936 int i=0; 1937 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { 1938 LOG(5, "INFO: Adding NormalVector " << runner->second->NormalVector << " of triangle " << *(runner->second) << "."); 1939 OtherEndpoint[(i+1)%2] = runner->second->GetThirdEndpoint(Base)->node->getPosition(); 1940 BaseLineNormal[i++] = (runner->second->NormalVector); 1941 ASSERT( i <= 2, 1942 "Tesselation::FlipBaseline() - not exactly two triangles found."); 1943 } 1944 } 1914 1945 1915 1946 // get the two triangles … … 1941 1972 1942 1973 // index OldLines and OldPoints 1974 // note that oldlines[0,1] belong to first triangle and hence first normal 1975 // vector and oldlines[2,3] belong to second triangle and its normal vector 1943 1976 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) 1944 1977 for (int j = 0; j < 3; j++) // all of their endpoints and baselines … … 1950 1983 OldPoints[m++] = runner->second->endpoints[j]; 1951 1984 1985 Vector BasePoints[2]; // endpoints of Base 1986 if (OldLines[0]->ContainsBoundaryPoint(Base->endpoints[0])) { 1987 BasePoints[0] = Base->endpoints[0]->node->getPosition(); 1988 BasePoints[1] = Base->endpoints[1]->node->getPosition(); 1989 } else { 1990 BasePoints[0] = Base->endpoints[1]->node->getPosition(); 1991 BasePoints[1] = Base->endpoints[0]->node->getPosition(); 1992 } 1952 1993 // check whether everything is in place to create new lines and triangles 1953 1994 if (i < 4) { … … 1965 2006 return NULL; 1966 2007 } 2008 2009 // construct plane of first triangle for calculating normal vectors later 2010 const Plane triangleplane = Base->triangles.begin()->second->getPlane(); 2011 // get fourth point projected down onto this plane 2012 const Vector Intersection = triangleplane.getClosestPoint(OtherEndpoint[0]); 1967 2013 1968 2014 // remove triangles and baseline removes itself … … 1971 2017 m = 0; 1972 2018 // first obtain all triangle to delete ... (otherwise we pull the carpet (Base) from under the for-loop's feet) 1973 list 2019 list<BoundaryTriangleSet *> TrianglesOfBase; 1974 2020 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); ++runner) 1975 2021 TrianglesOfBase.push_back(runner->second); 1976 2022 // .. then delete each triangle (which deletes the line as well) 1977 for (list 2023 for (list<BoundaryTriangleSet *>::iterator runner = TrianglesOfBase.begin(); !TrianglesOfBase.empty(); runner = TrianglesOfBase.begin()) { 1978 2024 LOG(3, "DEBUG: Deleting triangle " << *(*runner) << "."); 1979 2025 OldTriangleNrs[m++] = (*runner)->Nr; … … 1988 2034 LinesOnBoundary.insert(LinePair(OldBaseLineNr, NewLine)); // no need for check for unique insertion as NewLine is definitely a new one 1989 2035 LOG(3, "DEBUG: Created new baseline " << *NewLine << "."); 2036 2037 // Explanation for normal vector choice: 2038 // Decisive for the normal vector of the new triangle is whether the fourth 2039 // endpoint is with respect to the joining boundary line on one side or on 2040 // the other with respect to the endpoint of the plane triangle that is not 2041 // contained in the joining boundary line. 1990 2042 1991 2043 // construct new triangles with flipped baseline … … 2000 2052 BLS[2] = NewLine; 2001 2053 BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[0]); 2002 BTS->GetNormalVector(BaseLineNormal); 2054 { 2055 Line joiningline = makeLineThrough( 2056 OldLines[0]->endpoints[0]->node->getPosition(), 2057 OldLines[0]->endpoints[1]->node->getPosition()); 2058 // BasePoints[1] is not contained in OldLines[0], hence is third endpoint 2059 // of plane triangle. BasePoints[0] is in the joining OldLines[0] and 2060 // we check whether Intersection is on same side as BasePoints[1] or not. 2061 const Vector pointinginside = 2062 joiningline.getClosestPoint(BasePoints[1]) - BasePoints[1]; 2063 const Vector pointingtointersection = 2064 joiningline.getClosestPoint(Intersection) - Intersection; 2065 const double sign_of_intersection = 2066 pointingtointersection.ScalarProduct(pointinginside); 2067 LOG(4, "DEBUG: Sign of SKP between both lines w.r.t " << *OldLines[0] 2068 << " is " << sign_of_intersection << "."); 2069 const double sign_of_normal = (sign_of_intersection >= 0) ? -1. : +1.; 2070 LOG(4, "DEBUG: Opposite normal direction is " 2071 << sign_of_normal * BaseLineNormal[0] << "."); 2072 BTS->GetNormalVector(sign_of_normal * BaseLineNormal[0]); 2073 } 2003 2074 AddTesselationTriangle(OldTriangleNrs[0]); 2004 2075 LOG(3, "DEBUG: Created new triangle " << *BTS << "."); … … 2008 2079 BLS[2] = NewLine; 2009 2080 BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[1]); 2010 BTS->GetNormalVector(BaseLineNormal); 2081 { 2082 Line joiningline = makeLineThrough( 2083 OldLines[1]->endpoints[0]->node->getPosition(), 2084 OldLines[1]->endpoints[1]->node->getPosition()); 2085 // BasePoints[0] is not contained in OldLines[1], hence is third endpoint 2086 // of plane triangle. BasePoints[1] is in th1e joining OldLines[1] and 2087 // we check whether Intersection is on same side as BasePoints[0] or not. 2088 const Vector pointinginside = 2089 joiningline.getClosestPoint(BasePoints[0]) - BasePoints[0]; 2090 const Vector pointingtointersection = 2091 joiningline.getClosestPoint(Intersection) - Intersection; 2092 const double sign_of_intersection = 2093 pointingtointersection.ScalarProduct(pointinginside); 2094 LOG(4, "DEBUG: Sign of SKP between both lines w.r.t " << *OldLines[1] 2095 << " is " << sign_of_intersection << "."); 2096 const double sign_of_normal = (sign_of_intersection >= 0) ? -1. : +1.; 2097 LOG(4, "DEBUG: Opposite normal direction is " 2098 << sign_of_normal * BaseLineNormal[0] << "."); 2099 BTS->GetNormalVector(sign_of_normal * BaseLineNormal[0]); 2100 } 2011 2101 AddTesselationTriangle(OldTriangleNrs[1]); 2012 2102 LOG(3, "DEBUG: Created new triangle " << *BTS << "."); … … 2155 2245 TesselPoint *Candidate = NULL; 2156 2246 2157 LOG( 3, "DEBUG: NormalVector of BaseTriangle is " << NormalVector << ".");2247 LOG(4, "DEBUG: NormalVector of BaseTriangle is " << NormalVector << "."); 2158 2248 2159 2249 // copy old center … … 2163 2253 2164 2254 // construct center of circle 2165 CircleCenter = 0.5 * ((CandidateLine.BaseLine->endpoints[0]->node->getPosition()) + 2166 (CandidateLine.BaseLine->endpoints[1]->node->getPosition())); 2255 CircleCenter = 0.5 * ((CandidateLine.BaseLine->endpoints[0]->node->getPosition()) + (CandidateLine.BaseLine->endpoints[1]->node->getPosition())); 2167 2256 2168 2257 // construct normal vector of circle 2169 CirclePlaneNormal = (CandidateLine.BaseLine->endpoints[0]->node->getPosition()) - 2170 (CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 2258 CirclePlaneNormal = (CandidateLine.BaseLine->endpoints[0]->node->getPosition()) - (CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 2171 2259 2172 2260 RelativeOldSphereCenter = OldSphereCenter - CircleCenter; … … 2177 2265 CircleRadius = RADIUS * RADIUS - radius; 2178 2266 CirclePlaneNormal.Normalize(); 2179 LOG( 3, "DEBUG: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << ".");2267 LOG(4, "DEBUG: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "."); 2180 2268 2181 2269 // test whether old center is on the band's plane … … 2186 2274 radius = RelativeOldSphereCenter.NormSquared(); 2187 2275 if (fabs(radius - CircleRadius) < HULLEPSILON) { 2188 LOG( 3, "DEBUG: RelativeOldSphereCenter is at " << RelativeOldSphereCenter << ".");2276 LOG(4, "DEBUG: RelativeOldSphereCenter is at " << RelativeOldSphereCenter << "."); 2189 2277 2190 2278 // check SearchDirection 2191 LOG( 3, "DEBUG: SearchDirection is " << SearchDirection << ".");2279 LOG(4, "DEBUG: SearchDirection is " << SearchDirection << "."); 2192 2280 if (fabs(RelativeOldSphereCenter.ScalarProduct(SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2193 2281 ELOG(1, "SearchDirection and RelativeOldSphereCenter are not orthogonal!"); … … 2230 2318 // find center on the plane 2231 2319 GetCenterofCircumcircle(NewPlaneCenter, CandidateLine.BaseLine->endpoints[0]->node->getPosition(), CandidateLine.BaseLine->endpoints[1]->node->getPosition(), Candidate->getPosition()); 2232 LOG( 3, "DEBUG: NewPlaneCenter is " << NewPlaneCenter << ".");2320 LOG(5, "DEBUG: NewPlaneCenter is " << NewPlaneCenter << "."); 2233 2321 2234 2322 try { 2235 NewNormalVector = Plane((CandidateLine.BaseLine->endpoints[0]->node->getPosition()), 2236 (CandidateLine.BaseLine->endpoints[1]->node->getPosition()), 2237 (Candidate->getPosition())).getNormal(); 2238 LOG(3, "DEBUG: NewNormalVector is " << NewNormalVector << "."); 2323 NewNormalVector = Plane((CandidateLine.BaseLine->endpoints[0]->node->getPosition()), (CandidateLine.BaseLine->endpoints[1]->node->getPosition()), (Candidate->getPosition())).getNormal(); 2324 LOG(5, "DEBUG: NewNormalVector is " << NewNormalVector << "."); 2239 2325 radius = CandidateLine.BaseLine->endpoints[0]->node->DistanceSquared(NewPlaneCenter); 2240 LOG( 3, "DEBUG: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << ".");2241 LOG( 3, "DEBUG: SearchDirection is " << SearchDirection << ".");2242 LOG( 3, "DEBUG: Radius of CircumCenterCircle is " << radius << ".");2326 LOG(5, "DEBUG: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "."); 2327 LOG(5, "DEBUG: SearchDirection is " << SearchDirection << "."); 2328 LOG(5, "DEBUG: Radius of CircumCenterCircle is " << radius << "."); 2243 2329 if (radius < RADIUS * RADIUS) { 2244 2330 otherradius = CandidateLine.BaseLine->endpoints[1]->node->DistanceSquared(NewPlaneCenter); … … 2246 2332 // construct both new centers 2247 2333 NewSphereCenter = NewPlaneCenter; 2248 OtherNewSphereCenter = NewPlaneCenter;2334 OtherNewSphereCenter = NewPlaneCenter; 2249 2335 helper = NewNormalVector; 2250 2336 helper.Scale(sqrt(RADIUS * RADIUS - radius)); 2251 LOG( 4, "DEBUG: Distance of NewPlaneCenter " << NewPlaneCenter << " to either NewSphereCenter is " << helper.Norm() << " of vector " << helper << " with sphere radius " << RADIUS << ".");2337 LOG(5, "DEBUG: Distance of NewPlaneCenter " << NewPlaneCenter << " to either NewSphereCenter is " << helper.Norm() << " of vector " << helper << " with sphere radius " << RADIUS << "."); 2252 2338 NewSphereCenter += helper; 2253 LOG( 4, "DEBUG: NewSphereCenter is at " << NewSphereCenter << ".");2339 LOG(5, "DEBUG: NewSphereCenter is at " << NewSphereCenter << "."); 2254 2340 // OtherNewSphereCenter is created by the same vector just in the other direction 2255 2341 helper.Scale(-1.); 2256 2342 OtherNewSphereCenter += helper; 2257 LOG( 4, "DEBUG: OtherNewSphereCenter is at " << OtherNewSphereCenter << ".");2343 LOG(5, "DEBUG: OtherNewSphereCenter is at " << OtherNewSphereCenter << "."); 2258 2344 alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection, HULLEPSILON); 2259 2345 Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection, HULLEPSILON); … … 2276 2362 if ((CandidateLine.ShortestAngle - HULLEPSILON) < alpha) { 2277 2363 CandidateLine.pointlist.push_back(Candidate); 2278 LOG( 2, "ACCEPT: We have found an equally good candidate: " << *(Candidate) << " with " << alpha << " and circumsphere's center at " << CandidateLine.OptCenter << ".");2364 LOG(3, "ACCEPT: We have found an equally good candidate: " << *(Candidate) << " with " << alpha << " and circumsphere's center at " << CandidateLine.OptCenter << "."); 2279 2365 } else { 2280 2366 // remove all candidates from the list and then the list itself 2281 2367 CandidateLine.pointlist.clear(); 2282 2368 CandidateLine.pointlist.push_back(Candidate); 2283 LOG( 2, "ACCEPT: We have found a better candidate: " << *(Candidate) << " with " << alpha << " and circumsphere's center at " << CandidateLine.OptCenter << ".");2369 LOG(3, "ACCEPT: We have found a better candidate: " << *(Candidate) << " with " << alpha << " and circumsphere's center at " << CandidateLine.OptCenter << "."); 2284 2370 } 2285 2371 CandidateLine.ShortestAngle = alpha; 2286 LOG( 2, "DEBUG: There are " << CandidateLine.pointlist.size() << " candidates in the list now.");2372 LOG(4, "DEBUG: There are " << CandidateLine.pointlist.size() << " candidates in the list now."); 2287 2373 } else { 2288 2374 if ((Candidate != NULL) && (CandidateLine.pointlist.begin() != CandidateLine.pointlist.end())) { 2289 LOG( 3, "REJECT: Old candidate " << *(*CandidateLine.pointlist.begin()) << " with " << CandidateLine.ShortestAngle << " is better than new one " << *Candidate << " with " << alpha << " .");2375 LOG(4, "REJECT: Old candidate " << *(*CandidateLine.pointlist.begin()) << " with " << CandidateLine.ShortestAngle << " is better than new one " << *Candidate << " with " << alpha << " ."); 2290 2376 } else { 2291 LOG( 3, "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected.");2377 LOG(4, "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected."); 2292 2378 } 2293 2379 } 2294 2380 } else { 2295 ELOG(0, "REJECT: Distance to center of circumcircle is not the same from each corner of the triangle: " << fabs(radius - otherradius));2381 ASSERT(0, std::string("FindThirdPointForTesselation() - ") + std::string("REJECT: Distance to center of circumcircle is not the same from each corner of the triangle: ") + toString(fabs(radius - otherradius))); 2296 2382 } 2297 2383 } else { 2298 LOG( 3, "REJECT: NewSphereCenter " << NewSphereCenter << " for " << *Candidate << " is too far away: " << radius << ".");2384 LOG(4, "REJECT: NewSphereCenter " << NewSphereCenter << " for " << *Candidate << " is too far away: " << radius << "."); 2299 2385 } 2300 } 2301 catch (LinearDependenceException &excp){ 2302 LOG(3, boost::diagnostic_information(excp)); 2303 LOG(3, "REJECT: Three points from " << *CandidateLine.BaseLine << " and Candidate " << *Candidate << " are linear-dependent."); 2386 } catch (LinearDependenceException &excp) { 2387 LOG(4, boost::diagnostic_information(excp)); 2388 LOG(4, "REJECT: Three points from " << *CandidateLine.BaseLine << " and Candidate " << *Candidate << " are linear-dependent."); 2304 2389 } 2305 2390 } else { 2306 2391 if (ThirdPoint != NULL) { 2307 LOG( 3, "REJECT: Base triangle " << *CandidateLine.BaseLine << " and " << *ThirdPoint << " contains Candidate " << *Candidate << ".");2392 LOG(4, "REJECT: Base triangle " << *CandidateLine.BaseLine << " and " << *ThirdPoint << " contains Candidate " << *Candidate << "."); 2308 2393 } else { 2309 LOG( 3, "REJECT: Base triangle " << *CandidateLine.BaseLine << " contains Candidate " << *Candidate << ".");2394 LOG(4, "REJECT: Base triangle " << *CandidateLine.BaseLine << " contains Candidate " << *Candidate << "."); 2310 2395 } 2311 2396 } … … 2318 2403 } else { 2319 2404 if (ThirdPoint != NULL) 2320 LOG( 3, "Circumcircle for base line " << *CandidateLine.BaseLine << " and third node " << *ThirdPoint << " is too big!");2405 LOG(4, "DEBUG: Circumcircle for base line " << *CandidateLine.BaseLine << " and third node " << *ThirdPoint << " is too big!"); 2321 2406 else 2322 LOG( 3, "Circumcircle for base line " << *CandidateLine.BaseLine << " is too big!");2323 } 2324 2325 LOG( 2, "DEBUG: Sorting candidate list ...");2407 LOG(4, "DEBUG: Circumcircle for base line " << *CandidateLine.BaseLine << " is too big!"); 2408 } 2409 2410 LOG(5, "DEBUG: Sorting candidate list ..."); 2326 2411 if (CandidateLine.pointlist.size() > 1) { 2327 2412 CandidateLine.pointlist.unique(); … … 2329 2414 } 2330 2415 2331 if ((!CandidateLine.pointlist.empty()) && (!CandidateLine.CheckValidity(RADIUS, LC))) { 2332 ELOG(0, "There were other points contained in the rolling sphere as well!"); 2333 performCriticalExit(); 2334 } 2416 ASSERT(CandidateLine.pointlist.empty() || (CandidateLine.CheckValidity(RADIUS, LC)), std::string("Tesselation::FindThirdPointForTesselation()") + std::string("There were other points contained in the rolling sphere as well!")); 2335 2417 } 2336 2418 ; … … 2344 2426 { 2345 2427 //Info FunctionInfo(__func__); 2346 const BoundaryLineSet * lines[2] = { line1, line2};2428 const BoundaryLineSet * lines[2] = {line1, line2}; 2347 2429 class BoundaryPointSet *node = NULL; 2348 2430 PointMap OrderMap; … … 2351 2433 // for both lines 2352 2434 for (int j = 0; j < 2; j++) { // for both endpoints 2353 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> 2435 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *>(lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j])); 2354 2436 if (!OrderTest.second) { // if insertion fails, we have common endpoint 2355 2437 node = OrderTest.first->second; … … 2400 2482 // we should make sure that both triangles end up in the same entry 2401 2483 // in the distance multimap. Hence, we round to 6 digit precision. 2402 const double distance = 2403 1e-6*floor(FindPoint->second->node->DistanceSquared(x)*1e+6); 2484 const double distance = 1e-6 * floor(FindPoint->second->node->DistanceSquared(x) * 1e+6); 2404 2485 points->insert(DistanceToPointPair(distance, FindPoint->second)); 2405 2486 LOG(3, "DEBUG: Putting " << *FindPoint->second << " into the list."); … … 2446 2527 for (LineMap::iterator LineRunner = Runner->second->lines.begin(); LineRunner != Runner->second->lines.end(); LineRunner++) { 2447 2528 // calculate closest point on line to desired point 2448 helper = 0.5 * (((LineRunner->second)->endpoints[0]->node->getPosition()) + 2449 ((LineRunner->second)->endpoints[1]->node->getPosition())); 2529 helper = 0.5 * (((LineRunner->second)->endpoints[0]->node->getPosition()) + ((LineRunner->second)->endpoints[1]->node->getPosition())); 2450 2530 Center = (x) - helper; 2451 BaseLine = ((LineRunner->second)->endpoints[0]->node->getPosition()) - 2452 ((LineRunner->second)->endpoints[1]->node->getPosition()); 2531 BaseLine = ((LineRunner->second)->endpoints[0]->node->getPosition()) - ((LineRunner->second)->endpoints[1]->node->getPosition()); 2453 2532 Center.ProjectOntoPlane(BaseLine); 2454 2533 const double distance = Center.NormSquared(); … … 2507 2586 for (LineMap::iterator LineRunner = Runner->second->lines.begin(); LineRunner != Runner->second->lines.end(); LineRunner++) { 2508 2587 2509 BaseLine = ((LineRunner->second)->endpoints[0]->node->getPosition()) - 2510 ((LineRunner->second)->endpoints[1]->node->getPosition()); 2588 BaseLine = ((LineRunner->second)->endpoints[0]->node->getPosition()) - ((LineRunner->second)->endpoints[1]->node->getPosition()); 2511 2589 const double lengthBase = BaseLine.NormSquared(); 2512 2590 … … 2524 2602 MinDistance = lengthEnd; 2525 2603 LOG(1, "ACCEPT: Line " << *LineRunner->second << " to endpoint " << *LineRunner->second->endpoints[0]->node << " is closer with " << lengthEnd << "."); 2526 } else if (fabs(lengthEnd - MinDistance) < MYEPSILON) { // additional best candidate 2527 ClosestLines.insert(LineRunner->second); 2528 LOG(1, "ACCEPT: Line " << *LineRunner->second << " to endpoint " << *LineRunner->second->endpoints[1]->node << " is equally good with " << lengthEnd << "."); 2529 } else { // line is worse 2530 LOG(1, "REJECT: Line " << *LineRunner->second << " to either endpoints is further away than present closest line candidate: " << lengthEndA << ", " << lengthEndB << ", and distance is longer than baseline:" << lengthBase << "."); 2531 } 2604 } else 2605 if (fabs(lengthEnd - MinDistance) < MYEPSILON) { // additional best candidate 2606 ClosestLines.insert(LineRunner->second); 2607 LOG(1, "ACCEPT: Line " << *LineRunner->second << " to endpoint " << *LineRunner->second->endpoints[1]->node << " is equally good with " << lengthEnd << "."); 2608 } else { // line is worse 2609 LOG(1, "REJECT: Line " << *LineRunner->second << " to either endpoints is further away than present closest line candidate: " << lengthEndA << ", " << lengthEndB << ", and distance is longer than baseline:" << lengthBase << "."); 2610 } 2532 2611 } else { // intersection is closer, calculate 2533 2612 // calculate closest point on line to desired point … … 2655 2734 double distance = 0.; 2656 2735 2657 if (triangle == NULL) { // is boundary point or only point in point cloud?2736 if (triangle == NULL) { // is boundary point or only point in point cloud? 2658 2737 LOG(1, "No triangle given!"); 2659 2738 return -1.; … … 2764 2843 takePoint = true; 2765 2844 current = findLines->second->endpoints[1]->node; 2766 } else if (findLines->second->endpoints[1]->Nr == Point->getNr()) { 2767 takePoint = true; 2768 current = findLines->second->endpoints[0]->node; 2769 } 2845 } else 2846 if (findLines->second->endpoints[1]->Nr == Point->getNr()) { 2847 takePoint = true; 2848 current = findLines->second->endpoints[0]->node; 2849 } 2770 2850 2771 2851 if (takePoint) { … … 2807 2887 Vector OrthogonalVector; 2808 2888 Vector helper; 2809 const TesselPoint * const TrianglePoints[3] = { Point, NULL, NULL};2889 const TesselPoint * const TrianglePoints[3] = {Point, NULL, NULL}; 2810 2890 TriangleList *triangles = NULL; 2811 2891 … … 2818 2898 // calculate central point 2819 2899 triangles = FindTriangles(TrianglePoints); 2820 if ((triangles != NULL) && (!triangles->empty())) { 2821 for (TriangleList::iterator Runner = triangles->begin(); Runner != triangles->end(); Runner++) 2822 PlaneNormal += (*Runner)->NormalVector; 2823 } else { 2824 ELOG(0, "Could not find any triangles for point " << *Point << "."); 2825 performCriticalExit(); 2826 } 2900 ASSERT((triangles == NULL) || (triangles->empty()), std::string("Tesselation::GetCircleOfConnectedTriangles()") + std::string("Could not find any triangles for point " + toString(*Point) + ".")); 2901 for (TriangleList::iterator Runner = triangles->begin(); Runner != triangles->end(); Runner++) 2902 PlaneNormal += (*Runner)->NormalVector; 2827 2903 PlaneNormal.Scale(1.0 / triangles->size()); 2828 2904 LOG(4, "DEBUG: Calculated PlaneNormal of all circle points is " << PlaneNormal << "."); … … 2836 2912 AngleZero = ((*SetOfNeighbours->begin())->getPosition()) - (Point->getPosition()); 2837 2913 AngleZero.ProjectOntoPlane(PlaneNormal); 2838 if (AngleZero.NormSquared() < MYEPSILON) { 2839 ELOG(0, "CRITIAL: AngleZero is 0 even with alternative reference. The algorithm has to be changed here!"); 2840 performCriticalExit(); 2841 } 2914 ASSERT(AngleZero.NormSquared() > MYEPSILON, std::string("Tesselation::GetCircleOfConnectedTriangles() - ") + std::string("AngleZero is 0 even with alternative reference.") + std::string("The algorithm has to be changed here!")); 2842 2915 } 2843 2916 LOG(4, "DEBUG: Reference vector on this plane representing angle 0 is " << AngleZero << "."); 2844 2917 if (AngleZero.NormSquared() > MYEPSILON) 2845 OrthogonalVector = Plane(PlaneNormal, AngleZero, 0).getNormal();2918 OrthogonalVector = Plane(PlaneNormal, AngleZero, 0).getNormal(); 2846 2919 else 2847 2920 OrthogonalVector.MakeNormalTo(PlaneNormal); … … 2854 2927 double angle = GetAngle(helper, AngleZero, OrthogonalVector); 2855 2928 LOG(4, "DEBUG" << angle << " for point " << **listRunner << "."); 2856 anglesOfPoints.insert(pair<double, TesselPoint*> 2929 anglesOfPoints.insert(pair<double, TesselPoint*>(angle, (*listRunner))); 2857 2930 } 2858 2931 … … 2909 2982 int counter = 0; 2910 2983 while (TesselC != SetOfNeighbours->end()) { 2911 helper = Plane(((*TesselA)->getPosition()), 2912 ((*TesselB)->getPosition()), 2913 ((*TesselC)->getPosition())).getNormal(); 2984 helper = Plane(((*TesselA)->getPosition()), ((*TesselB)->getPosition()), ((*TesselC)->getPosition())).getNormal(); 2914 2985 LOG(5, "DEBUG: Making normal vector out of " << *(*TesselA) << ", " << *(*TesselB) << " and " << *(*TesselC) << ":" << helper); 2915 2986 counter++; … … 2920 2991 } 2921 2992 //LOG(0, "Summed vectors " << center << "; number of points " << connectedPoints.size() << "; scale factor " << counter); 2922 PlaneNormal.Scale(1.0 / (double) 2993 PlaneNormal.Scale(1.0 / (double)counter); 2923 2994 // LOG(1, "INFO: Calculated center of all circle points is " << center << "."); 2924 2995 // … … 2934 3005 AngleZero.ProjectOntoPlane(PlaneNormal); 2935 3006 } 2936 if ((Reference.IsZero()) || (AngleZero.NormSquared() < MYEPSILON 3007 if ((Reference.IsZero()) || (AngleZero.NormSquared() < MYEPSILON)) { 2937 3008 LOG(4, "DEBUG: Using alternatively " << (*SetOfNeighbours->begin())->getPosition() << " as angle 0 referencer."); 2938 3009 AngleZero = ((*SetOfNeighbours->begin())->getPosition()) - (Point->getPosition()); 2939 3010 AngleZero.ProjectOntoPlane(PlaneNormal); 2940 if (AngleZero.NormSquared() < MYEPSILON) { 2941 ELOG(0, "CRITIAL: AngleZero is 0 even with alternative reference. The algorithm has to be changed here!"); 2942 performCriticalExit(); 2943 } 3011 ASSERT(AngleZero.NormSquared() > MYEPSILON, std::string("Tesselation::GetCircleOfSetOfPoints() - ") + std::string("AngleZero is 0 even with alternative reference.") + std::string("The algorithm has to be changed here!")); 2944 3012 } 2945 3013 LOG(4, "DEBUG: Reference vector on this plane representing angle 0 is " << AngleZero << "."); 2946 3014 if (AngleZero.NormSquared() > MYEPSILON) 2947 OrthogonalVector = Plane(PlaneNormal, AngleZero, 0).getNormal();3015 OrthogonalVector = Plane(PlaneNormal, AngleZero, 0).getNormal(); 2948 3016 else 2949 3017 OrthogonalVector.MakeNormalTo(PlaneNormal); … … 2959 3027 angle = 2. * M_PI - angle; 2960 3028 LOG(4, "DEBUG: Calculated angle between " << helper << " and " << AngleZero << " is " << angle << " for point " << **listRunner << "."); 2961 InserterTest = anglesOfPoints.insert(pair<double, TesselPoint*> (angle, (*listRunner))); 2962 if (!InserterTest.second) { 2963 ELOG(0, "GetCircleOfSetOfPoints() got two atoms with same angle: " << *((InserterTest.first)->second) << " and " << (*listRunner)); 2964 performCriticalExit(); 2965 } 3029 InserterTest = anglesOfPoints.insert(pair<double, TesselPoint*>(angle, (*listRunner))); 3030 ASSERT(InserterTest.second, std::string("Tesselation::GetCircleOfSetOfPoints() - ") + std::string("got two atoms with same angle " + toString(*((InserterTest.first)->second))) + std::string(" and " + toString((*listRunner)))); 2966 3031 } 2967 3032 … … 2983 3048 //Info FunctionInfo(__func__); 2984 3049 map<double, TesselPoint*> anglesOfPoints; 2985 list<TesselPointList *> *ListOfPaths = new list<TesselPointList *> 3050 list<TesselPointList *> *ListOfPaths = new list<TesselPointList *>; 2986 3051 TesselPointList *connectedPath = NULL; 2987 3052 Vector center; … … 3009 3074 map<class BoundaryTriangleSet *, bool>::iterator TriangleRunner; 3010 3075 for (LineMap::iterator Runner = ReferencePoint->lines.begin(); Runner != ReferencePoint->lines.end(); Runner++) { 3011 TouchedLine.insert(pair<class BoundaryLineSet *, bool> (Runner->second, false)); 3012 for (TriangleMap::iterator Sprinter = Runner->second->triangles.begin(); Sprinter != Runner->second->triangles.end(); Sprinter++) 3013 TouchedTriangle.insert(pair<class BoundaryTriangleSet *, bool> (Sprinter->second, false)); 3076 LOG(4, "DEBUG: Adding " << *Runner->second << " to TouchedLine map."); 3077 TouchedLine.insert(pair<class BoundaryLineSet *, bool>(Runner->second, false)); 3078 for (TriangleMap::iterator Sprinter = Runner->second->triangles.begin(); Sprinter != Runner->second->triangles.end(); Sprinter++) { 3079 LOG(4, "DEBUG: Adding " << *Sprinter->second << " to TouchedTriangle map."); 3080 TouchedTriangle.insert(pair<class BoundaryTriangleSet *, bool>(Sprinter->second, false)); 3081 } 3014 3082 } 3015 3083 if (!ReferencePoint->lines.empty()) { … … 3018 3086 if (LineRunner == TouchedLine.end()) { 3019 3087 ELOG(1, "I could not find " << *runner->second << " in the touched list."); 3020 } else if (!LineRunner->second) { 3021 LineRunner->second = true; 3022 connectedPath = new TesselPointList; 3023 triangle = NULL; 3024 CurrentLine = runner->second; 3025 StartLine = CurrentLine; 3026 CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint); 3027 LOG(1, "INFO: Beginning path retrieval at " << *CurrentPoint << " of line " << *CurrentLine << "."); 3028 do { 3029 // push current one 3030 LOG(1, "INFO: Putting " << *CurrentPoint << " at end of path."); 3031 connectedPath->push_back(CurrentPoint->node); 3032 3033 // find next triangle 3034 for (TriangleMap::iterator Runner = CurrentLine->triangles.begin(); Runner != CurrentLine->triangles.end(); Runner++) { 3035 LOG(1, "INFO: Inspecting triangle " << *Runner->second << "."); 3036 if ((Runner->second != triangle)) { // look for first triangle not equal to old one 3037 triangle = Runner->second; 3038 TriangleRunner = TouchedTriangle.find(triangle); 3039 if (TriangleRunner != TouchedTriangle.end()) { 3040 if (!TriangleRunner->second) { 3041 TriangleRunner->second = true; 3042 LOG(1, "INFO: Connecting triangle is " << *triangle << "."); 3043 break; 3088 } else 3089 if (!LineRunner->second) { 3090 LineRunner->second = true; 3091 connectedPath = new TesselPointList; 3092 triangle = NULL; 3093 CurrentLine = runner->second; 3094 StartLine = CurrentLine; 3095 CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint); 3096 LOG(3, "INFO: Beginning path retrieval at " << *CurrentPoint << " of line " << *CurrentLine << "."); 3097 do { 3098 // push current one 3099 LOG(3, "INFO: Putting " << *CurrentPoint << " at end of path."); 3100 connectedPath->push_back(CurrentPoint->node); 3101 3102 // find next triangle 3103 for (TriangleMap::iterator Runner = CurrentLine->triangles.begin(); Runner != CurrentLine->triangles.end(); Runner++) { 3104 LOG(4, "DEBUG: Inspecting triangle " << *Runner->second << "."); 3105 if ((Runner->second != triangle)) { // look for first triangle not equal to old one 3106 triangle = Runner->second; 3107 TriangleRunner = TouchedTriangle.find(triangle); 3108 if (TriangleRunner != TouchedTriangle.end()) { 3109 if (!TriangleRunner->second) { 3110 TriangleRunner->second = true; 3111 LOG(4, "DEBUG: Connecting triangle is " << *triangle << "."); 3112 break; 3113 } else { 3114 LOG(4, "DEBUG: Skipping " << *triangle << ", as we have already visited it."); 3115 triangle = NULL; 3116 } 3044 3117 } else { 3045 LOG(1, "INFO: Skipping " << *triangle << ", as we have already visited it.");3118 ELOG(1, "I could not find " << *triangle << " in the touched list."); 3046 3119 triangle = NULL; 3047 3120 } 3048 3121 } else { 3049 ELOG(1, "I could not find " << *triangle << " in the touched list.");3122 // as we have stumbled upon the same triangle, we don't need the check anymore 3050 3123 triangle = NULL; 3051 3124 } 3052 3125 } 3126 if (triangle == NULL) 3127 break; 3128 // find next line 3129 for (int i = 0; i < 3; i++) { 3130 if ((triangle->lines[i] != CurrentLine) && (triangle->lines[i]->ContainsBoundaryPoint(ReferencePoint))) { // not the current line and still containing Point 3131 CurrentLine = triangle->lines[i]; 3132 LOG(3, "INFO: Connecting line is " << *CurrentLine << "."); 3133 break; 3134 } 3135 } 3136 LineRunner = TouchedLine.find(CurrentLine); 3137 if (LineRunner == TouchedLine.end()) 3138 ELOG(1, "I could not find " << *CurrentLine << " in the touched list."); 3139 else 3140 LineRunner->second = true; 3141 // find next point 3142 CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint); 3143 3144 } while (CurrentLine != StartLine); 3145 // last point is missing, as it's on start line 3146 if (StartLine->GetOtherEndpoint(ReferencePoint)->node != connectedPath->back()) { 3147 LOG(3, "INFO: Putting " << *CurrentPoint << " at end of path to close it."); 3148 connectedPath->push_back(StartLine->GetOtherEndpoint(ReferencePoint)->node); 3053 3149 } 3054 if (triangle == NULL) 3055 break; 3056 // find next line 3057 for (int i = 0; i < 3; i++) { 3058 if ((triangle->lines[i] != CurrentLine) && (triangle->lines[i]->ContainsBoundaryPoint(ReferencePoint))) { // not the current line and still containing Point 3059 CurrentLine = triangle->lines[i]; 3060 LOG(1, "INFO: Connecting line is " << *CurrentLine << "."); 3061 break; 3062 } 3063 } 3064 LineRunner = TouchedLine.find(CurrentLine); 3065 if (LineRunner == TouchedLine.end()) 3066 ELOG(1, "I could not find " << *CurrentLine << " in the touched list."); 3067 else 3068 LineRunner->second = true; 3069 // find next point 3070 CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint); 3071 3072 } while (CurrentLine != StartLine); 3073 // last point is missing, as it's on start line 3074 LOG(1, "INFO: Putting " << *CurrentPoint << " at end of path."); 3075 if (StartLine->GetOtherEndpoint(ReferencePoint)->node != connectedPath->back()) 3076 connectedPath->push_back(StartLine->GetOtherEndpoint(ReferencePoint)->node); 3077 3078 ListOfPaths->push_back(connectedPath); 3079 } else { 3080 LOG(1, "INFO: Skipping " << *runner->second << ", as we have already visited it."); 3081 } 3150 3151 ListOfPaths->push_back(connectedPath); 3152 } else { 3153 LOG(3, "DEBUG: Skipping " << *runner->second << ", as we have already visited it."); 3154 } 3082 3155 } 3083 3156 } else { … … 3098 3171 //Info FunctionInfo(__func__); 3099 3172 list<TesselPointList *> *ListofPaths = GetPathsOfConnectedPoints(Point); 3100 list<TesselPointList *> *ListofClosedPaths = new list<TesselPointList *> 3173 list<TesselPointList *> *ListofClosedPaths = new list<TesselPointList *>; 3101 3174 TesselPointList *connectedPath = NULL; 3102 3175 TesselPointList *newPath = NULL; … … 3108 3181 connectedPath = *ListRunner; 3109 3182 3110 LOG(1, "INFO: Current path is " << connectedPath << "."); 3183 if (DoLog(2)) { 3184 std::stringstream output; 3185 output << "INFO: Current path is "; 3186 BOOST_FOREACH(const TesselPoint * const item, *connectedPath) { 3187 output << *item << " "; 3188 } 3189 LOG(1, output.str()); 3190 } 3111 3191 3112 3192 // go through list, look for reappearance of starting Point and count … … 3117 3197 if ((*CircleRunner == *CircleStart) && (CircleRunner != CircleStart)) { // is not the very first point 3118 3198 // we have a closed circle from Marker to new Marker 3119 if (DoLog( 1)) {3199 if (DoLog(3)) { 3120 3200 std::stringstream output; 3121 output << count + 1 << ". closed path consists of: "; 3122 for (TesselPointList::iterator CircleSprinter = Marker; 3123 CircleSprinter != CircleRunner; 3124 CircleSprinter++) 3201 output << "DEBUG: " << count + 1 << ". closed path consists of: "; 3202 for (TesselPointList::iterator CircleSprinter = Marker; CircleSprinter != CircleRunner; CircleSprinter++) 3125 3203 output << (**CircleSprinter) << " <-> "; 3126 3204 LOG(1, output.str()); … … 3138 3216 } 3139 3217 } 3140 LOG( 1, "INFO: " << count << " closed additional path(s) have been created.");3218 LOG(2, "DEBUG: " << count << " closed additional path(s) have been created."); 3141 3219 3142 3220 // delete list of paths … … 3176 3254 } 3177 3255 ; 3256 3257 struct CloserToPiHalf 3258 { 3259 bool operator()(double angle, double smallestangle) 3260 { 3261 return (fabs(angle - M_PI / 2.) < fabs(smallestangle - M_PI / 2.)); 3262 } 3263 }; 3264 3265 bool Tesselation::IsPointBelowSurroundingPolygon(const BoundaryPointSet *_point) const 3266 { 3267 // check for NULL 3268 if (_point == NULL) { 3269 return false; 3270 } 3271 3272 // get list of connected points 3273 if (_point->lines.empty()) { 3274 LOG(1, "INFO: point " << *_point << " is not connected to any lines."); 3275 return false; 3276 } 3277 bool PointIsBelow = true; 3278 3279 // create Orthogonal vector as reference for angle (pointing into [pi,2pi) interval) 3280 Vector OrthogonalVector; 3281 for (LineMap::const_iterator lineiter = _point->lines.begin(); 3282 lineiter != _point->lines.end(); ++lineiter) 3283 for (TriangleMap::const_iterator triangleiter = lineiter->second->triangles.begin(); 3284 triangleiter != lineiter->second->triangles.end(); 3285 ++triangleiter) 3286 OrthogonalVector += triangleiter->second->NormalVector; 3287 OrthogonalVector.Normalize(); 3288 3289 // go through all closed paths for this point 3290 typedef list<TesselPointList *> TPL_list_t; 3291 const TPL_list_t *ListOfClosedPaths = GetClosedPathsOfConnectedPoints(_point->node); 3292 for (TPL_list_t::const_iterator closedpathsiter = ListOfClosedPaths->begin(); 3293 (closedpathsiter != ListOfClosedPaths->end()) && PointIsBelow; 3294 ++closedpathsiter) { 3295 const TesselPointList *connectedPath = *closedpathsiter; 3296 3297 TesselPointList::const_iterator ListAdvance = connectedPath->begin(); // gives angle direction 3298 TesselPointList::const_iterator ListRunner = ListAdvance++; 3299 for (; (ListAdvance != connectedPath->end()) && PointIsBelow; 3300 ListRunner = ListAdvance++) { // go through all closed paths 3301 LOG(2, "DEBUG: Current reference node is " << **ListRunner 3302 << ", advanced node is " << **ListAdvance); 3303 3304 // reference vector to point to check for this point of connected path 3305 const Vector Reference = 3306 ((*ListAdvance)->getPosition()) - ((*ListRunner)->getPosition()); 3307 3308 // go through all other points in this connected path 3309 for (TesselPointList::const_iterator OtherRunner = ListAdvance; 3310 (OtherRunner != ListRunner) && PointIsBelow; 3311 ++OtherRunner == connectedPath->end() ? 3312 OtherRunner = connectedPath->begin() : 3313 OtherRunner) { 3314 if (OtherRunner == ListAdvance) 3315 continue; 3316 LOG(3, "DEBUG: Current other node is " << **OtherRunner); 3317 3318 // build the plane with normal vector 3319 const Vector onebeam = 3320 ((*OtherRunner)->getPosition()) - ((*ListAdvance)->getPosition()); 3321 Vector NormalVector = Reference; 3322 NormalVector.VectorProduct(onebeam); 3323 // needs to point in same general direction as average NormalVector of all triangles 3324 if (NormalVector.ScalarProduct(OrthogonalVector) < 0) 3325 NormalVector *= -1.; 3326 try { 3327 Plane plane(NormalVector, ((*ListRunner)->getPosition())); 3328 3329 // check whether point is below 3330 if (plane.SignedDistance(_point->node->getPosition()) > 0) { 3331 LOG(2, "DEBUG: For plane " << plane << " point " << *_point 3332 << " would remain above."); 3333 PointIsBelow = false; 3334 } 3335 } catch (ZeroVectorException &e) { 3336 ELOG(3, "Vectors are linear dependent, skipping."); 3337 } 3338 } 3339 } 3340 } 3341 delete ListOfClosedPaths; 3342 3343 return PointIsBelow; 3344 } 3345 3346 double Tesselation::RemovePointSurroundedByPolygon( 3347 TesselPointList *connectedPath, 3348 BoundaryPointSet *point) 3349 { 3350 double volume = 0.; 3351 const Vector OldPoint = point->node->getPosition(); 3352 3353 TesselPoint *oldNode = point->node; 3354 // remove present triangles for this connectedPath 3355 unsigned int count = 0; 3356 for (TesselPointList::const_iterator iter = connectedPath->begin(); 3357 iter != connectedPath->end(); ++iter) 3358 LOG(4, "DEBUG: Node in connectedPath is " << **iter); 3359 3360 { 3361 TesselPointList::iterator FirstNode, SecondNode; 3362 SecondNode = connectedPath->begin(); 3363 FirstNode = SecondNode++; 3364 for (;FirstNode != connectedPath->end(); ++SecondNode, ++FirstNode) { 3365 LOG(3, "DEBUG: MiddleNode is " << **FirstNode << "."); 3366 if (SecondNode == connectedPath->end()) 3367 SecondNode = connectedPath->begin(); 3368 TesselPoint *TriangleCandidates[3]; 3369 TriangleCandidates[0] = *FirstNode; 3370 TriangleCandidates[1] = *SecondNode; 3371 TriangleCandidates[2] = oldNode; 3372 BoundaryTriangleSet *triangle = GetPresentTriangle(TriangleCandidates); 3373 ASSERT( triangle != NULL, 3374 "Tesselation::RemovePointSurroundedByPolygon() - triangle to points " 3375 +toString((**SecondNode))+", "+toString((**FirstNode))+" and " 3376 +toString(*oldNode)+" does not exist."); 3377 LOG(3, "DEBUG: Removing triangle " << *triangle << "."); 3378 RemoveTesselationTriangle(triangle); 3379 ++count; 3380 } 3381 LOG(2, "INFO: " << count << " triangles were removed."); 3382 } 3383 3384 // re-create all triangles by going through connected points list 3385 LineList NewLines; 3386 typedef std::vector<double> angles_t; 3387 angles_t angles; 3388 count = 0; 3389 for (; !connectedPath->empty();) { 3390 // search middle node with widest angle to next neighbours 3391 TesselPointList::iterator StartNode, MiddleNode, EndNode; 3392 for (MiddleNode = connectedPath->begin(); MiddleNode != connectedPath->end(); MiddleNode++) { 3393 LOG(3, "INFO: MiddleNode is " << **MiddleNode << "."); 3394 // construct vectors to next and previous neighbour 3395 StartNode = MiddleNode; 3396 if (StartNode == connectedPath->begin()) 3397 StartNode = connectedPath->end(); 3398 StartNode--; 3399 //LOG(3, "INFO: StartNode is " << **StartNode << "."); 3400 const Vector Point = ((*StartNode)->getPosition()) - ((*MiddleNode)->getPosition()); 3401 EndNode = MiddleNode; 3402 EndNode++; 3403 if (EndNode == connectedPath->end()) 3404 EndNode = connectedPath->begin(); 3405 //LOG(3, "INFO: EndNode is " << **StartNode << "."); 3406 const Vector Reference = ((*EndNode)->getPosition()) - ((*MiddleNode)->getPosition()); 3407 Vector OrthogonalVector = ((*MiddleNode)->getPosition()) - OldPoint; 3408 OrthogonalVector.MakeNormalTo(Reference); 3409 angles.push_back(GetAngle(Point, Reference, OrthogonalVector)); 3410 } 3411 ASSERT( !angles.empty(), 3412 "Tesselation::RemovePointSurroundedByPolygon() - angles empty"); 3413 const angles_t::const_iterator maxiter = std::max_element(angles.begin(), angles.end()); 3414 angles_t::const_iterator miniter = angles.begin(); 3415 // distinguish between convex and nonconvex polygon 3416 if (*maxiter > M_PI) { 3417 // connectedPath is not convex: The idea is to fill any kinks pointing 3418 // inside into the connectedPath close to this concave spot first, making 3419 // it eventually become convex. 3420 // Hence, use adjacent (and convex) fill-in point 3421 miniter = (maxiter == angles.begin()) ? angles.end()-1 : maxiter-1; 3422 if (*miniter > M_PI) { 3423 miniter = (maxiter+1 == angles.end()) ? angles.begin() : maxiter+1; 3424 if (*miniter > M_PI) { 3425 miniter = std::min_element(angles.begin(), angles.end()); 3426 } 3427 } 3428 } else { 3429 // is convex 3430 miniter = std::min_element(angles.begin(), angles.end(), CloserToPiHalf()); 3431 } 3432 MiddleNode = connectedPath->begin(); 3433 std::advance(MiddleNode, std::distance(const_cast<const angles_t &>(angles).begin(), miniter)); 3434 3435 ASSERT(MiddleNode != connectedPath->end(), 3436 "Tesselation::RemovePointSurroundedByPolygon() - Could not find a smallest angle!"); 3437 angles.clear(); 3438 StartNode = MiddleNode; 3439 EndNode = MiddleNode; 3440 if (StartNode == connectedPath->begin()) 3441 StartNode = connectedPath->end(); 3442 StartNode--; 3443 EndNode++; 3444 if (EndNode == connectedPath->end()) 3445 EndNode = connectedPath->begin(); 3446 LOG(2, "INFO: StartNode is " << **StartNode << "."); 3447 LOG(2, "INFO: MiddleNode is " << **MiddleNode << "."); 3448 LOG(2, "INFO: EndNode is " << **EndNode << "."); 3449 LOG(1, "INFO: Attempting to create triangle " << (*StartNode)->getName() << ", " << (*MiddleNode)->getName() << " and " << (*EndNode)->getName() << "."); 3450 TesselPoint *TriangleCandidates[3]; 3451 TriangleCandidates[0] = *StartNode; 3452 TriangleCandidates[1] = *MiddleNode; 3453 TriangleCandidates[2] = *EndNode; 3454 BoundaryTriangleSet *triangle = GetPresentTriangle(TriangleCandidates); 3455 if (triangle != NULL) { 3456 const Vector center = 1./3. * ((*StartNode)->getPosition() 3457 + (*MiddleNode)->getPosition() 3458 + (*EndNode)->getPosition()); 3459 const Vector NormalVector = OldPoint - center; 3460 // check orientation of normal vector (that points inside) 3461 ASSERT( triangle->NormalVector.ScalarProduct(NormalVector) > std::numeric_limits<double>::epsilon()*1e2, 3462 "Tesselation::RemovePointSurroundedByPolygon() - New triangle with same orientation already present as " 3463 +toString(*triangle)+"!"); 3464 } 3465 3466 LOG(3, "DEBUG: Adding new triangle points."); 3467 AddTesselationPoint(*StartNode, 0); 3468 AddTesselationPoint(*MiddleNode, 1); 3469 AddTesselationPoint(*EndNode, 2); 3470 LOG(3, "DEBUG: Adding new triangle lines."); 3471 AddTesselationLine(NULL, NULL, TPS[0], TPS[1], 0); 3472 // line between start and end must be new (except for very last triangle) 3473 if (AddTesselationLine(NULL, NULL, TPS[0], TPS[2], 1)) 3474 NewLines.push_back(BLS[1]); 3475 AddTesselationLine(NULL, NULL, TPS[1], TPS[2], 2); 3476 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3477 const Vector center = 1./3. * ((*StartNode)->getPosition() 3478 + (*MiddleNode)->getPosition() 3479 + (*EndNode)->getPosition()); 3480 const Vector NormalVector = OldPoint - center; 3481 BTS->GetNormalVector(NormalVector); 3482 AddTesselationTriangle(); 3483 // calculate volume summand as a general tetraeder 3484 volume += CalculateVolumeofGeneralTetraeder( 3485 TPS[0]->node->getPosition(), 3486 TPS[1]->node->getPosition(), 3487 TPS[2]->node->getPosition(), 3488 OldPoint); 3489 // advance number 3490 ++count; 3491 3492 // prepare nodes for next triangle 3493 LOG(3, "DEBUG: Removing " << **MiddleNode << " from closed path."); 3494 connectedPath->remove(*MiddleNode); // remove the middle node (it is surrounded by triangles) 3495 LOG(3, "DEBUG: Remaining points: " << connectedPath->size() << "."); 3496 ASSERT(connectedPath->size() >= 2, 3497 "Tesselation::RemovePointSurroundedByPolygon() - There are only two endpoints left!"); 3498 if (connectedPath->size() == 2) { // we are done 3499 connectedPath->remove(*StartNode); // remove the start node 3500 connectedPath->remove(*EndNode); // remove the end node 3501 } 3502 } 3503 LOG(1, "INFO: " << count << " triangles were created."); 3504 3505 return volume; 3506 } 3178 3507 3179 3508 /** Removes a boundary point from the envelope while keeping it closed. … … 3190 3519 double Tesselation::RemovePointFromTesselatedSurface(class BoundaryPointSet *point) 3191 3520 { 3192 class BoundaryLineSet *line = NULL;3193 class BoundaryTriangleSet *triangle = NULL;3194 Vector OldPoint, NormalVector;3195 3521 double volume = 0; 3196 int count = 0;3197 3522 3198 3523 if (point == NULL) { … … 3202 3527 LOG(4, "DEBUG: Removing point " << *point << " from tesselated boundary ..."); 3203 3528 3204 // copy old location for the volume3205 OldPoint = (point->node->getPosition());3206 3207 3529 // get list of connected points 3208 3530 if (point->lines.empty()) { … … 3212 3534 3213 3535 list<TesselPointList *> *ListOfClosedPaths = GetClosedPathsOfConnectedPoints(point->node); 3214 TesselPointList *connectedPath = NULL; 3215 3216 // gather all triangles 3217 for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) 3218 count += LineRunner->second->triangles.size(); 3219 TriangleMap Candidates; 3220 for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) { 3221 line = LineRunner->second; 3222 for (TriangleMap::iterator TriangleRunner = line->triangles.begin(); TriangleRunner != line->triangles.end(); TriangleRunner++) { 3223 triangle = TriangleRunner->second; 3224 Candidates.insert(TrianglePair(triangle->Nr, triangle)); 3225 } 3226 } 3227 3228 // remove all triangles 3229 count = 0; 3230 NormalVector.Zero(); 3231 for (TriangleMap::iterator Runner = Candidates.begin(); Runner != Candidates.end(); Runner++) { 3232 LOG(1, "INFO: Removing triangle " << *(Runner->second) << "."); 3233 NormalVector -= Runner->second->NormalVector; // has to point inward 3234 RemoveTesselationTriangle(Runner->second); 3235 count++; 3236 } 3237 LOG(1, count << " triangles were removed."); 3238 3536 list<TesselPointList *>::iterator ListAdvance = ListOfClosedPaths->begin(); 3537 list<TesselPointList *>::iterator ListRunner = ListAdvance; 3538 // TriangleMap::iterator NumberRunner = Candidates.begin(); 3539 Vector Point, Reference, OrthogonalVector; 3540 for (; ListRunner != ListOfClosedPaths->end(); ListRunner = ListAdvance) { // go through all closed paths 3541 if (ListAdvance != ListOfClosedPaths->end()) 3542 ListAdvance++; 3543 3544 TesselPointList *connectedPath = *ListRunner; 3545 3546 volume += RemovePointSurroundedByPolygon(connectedPath, point); 3547 3548 ListOfClosedPaths->remove(connectedPath); 3549 delete (connectedPath); 3550 } 3551 delete (ListOfClosedPaths); 3552 3553 LOG(1, "INFO: Removed volume is " << volume << "."); 3554 3555 return volume; 3556 } 3557 ; 3558 3559 bool Tesselation::CheckAllConcaveInPolygon( 3560 const TesselPointList *connectedPath, 3561 const BoundaryPointSet *point 3562 ) 3563 { 3564 // check whether lines in this path to point to remove are all concave 3565 bool all_lines_concave = true; 3566 if (connectedPath->size() >= 2) { 3567 TesselPointList::const_iterator StartNode, MiddleNode, EndNode; 3568 // have nearest neighbors to a middle node to know adjacent triangles 3569 for (MiddleNode = connectedPath->begin(); 3570 all_lines_concave && (MiddleNode != connectedPath->end()); 3571 MiddleNode++) { 3572 LOG(3, "INFO: MiddleNode is " << **MiddleNode << "."); 3573 EndNode = MiddleNode; 3574 if (EndNode == connectedPath->begin()) 3575 EndNode = connectedPath->end(); 3576 --EndNode; 3577 StartNode = MiddleNode; 3578 ++StartNode; 3579 if (StartNode == connectedPath->end()) 3580 StartNode = connectedPath->begin(); 3581 3582 AddTesselationPoint(point->node, 0); 3583 AddTesselationPoint(*MiddleNode, 1); 3584 3585 ASSERT( point->lines.find((*MiddleNode)->getNr()) != point->lines.end(), 3586 "Tesselation::CheckAllConcaveInPolygon() - MiddleNode " 3587 +toString(**MiddleNode)+" not present in " 3588 +toString(*point)+"'s lines."); 3589 3590 // get line between Node and point and check 3591 std::pair<LineMap::const_iterator, LineMap::const_iterator> FindPair = 3592 point->lines.equal_range((*MiddleNode)->getNr()); 3593 LineMap::const_iterator FindLine = FindPair.first; 3594 for (; FindLine != FindPair.second; ++FindLine) { 3595 // line has got two triangles, check whether they resemble those 3596 // with start and endnode 3597 const BoundaryLineSet *currentline = FindLine->second; 3598 unsigned int matching_triangles = 0; 3599 for (TriangleMap::const_iterator triangleiter = currentline->triangles.begin(); 3600 triangleiter != currentline->triangles.end(); ++triangleiter) { 3601 const BoundaryTriangleSet *triangle = triangleiter->second; 3602 AddTesselationPoint(*StartNode, 2); 3603 if (triangle->IsPresentTupel(TPS)) 3604 ++matching_triangles; 3605 AddTesselationPoint(*EndNode, 2); 3606 if (triangle->IsPresentTupel(TPS)) 3607 ++matching_triangles; 3608 } 3609 if (matching_triangles == 2) 3610 break; 3611 } 3612 if (FindLine != FindPair.second) { 3613 LOG(3, "INFO: Current line of point " << *point << " is " << *FindLine->second << "."); 3614 all_lines_concave &= !FindLine->second->CheckConvexityCriterion(); 3615 } 3616 } 3617 } else { 3618 // check the single line 3619 if (connectedPath->empty()) 3620 return false; 3621 LineMap::const_iterator FindLine = point->lines.find((*connectedPath->begin())->getNr()); 3622 ASSERT( FindLine != point->lines.end(), 3623 "Tesselation::CheckAllConcaveInPolygon() - point " 3624 +toString((*connectedPath->begin())->getNr())+" not present in " 3625 +toString(*point)+"'s lines."); 3626 return !FindLine->second->CheckConvexityCriterion(); 3627 } 3628 3629 return all_lines_concave; 3630 } 3631 3632 /** Removes a boundary point from the envelope while keeping it closed. 3633 * We remove the old triangles connected to the point and re-create new triangles to close the surface following this ansatz: 3634 * -# a closed path(s) of boundary points surrounding the point to be removed is constructed 3635 * -# on each closed path, we pick three adjacent points, create a triangle with them and subtract the middle point from the path 3636 * -# we advance two points (i.e. the next triangle will start at the ending point of the last triangle) and continue as before 3637 * -# the surface is closed, when the path is empty 3638 * Thereby, we (hopefully) make sure that the removed points remains beneath the surface (this is checked via IsInnerPoint eventually). 3639 * \param *out output stream for debugging 3640 * \param *point point to be removed 3641 * \return volume added to the volume inside the tesselated surface by the removal 3642 */ 3643 double Tesselation::RemoveFullConcavePointFromTesselatedSurface(class BoundaryPointSet *point) 3644 { 3645 double volume = 0; 3646 3647 if (point == NULL) { 3648 ELOG(1, "Cannot remove the point " << point << ", it's NULL!"); 3649 return 0.; 3650 } else 3651 LOG(4, "DEBUG: Removing point " << *point << " from tesselated boundary ..."); 3652 3653 // get list of connected points 3654 if (point->lines.empty()) { 3655 ELOG(1, "Cannot remove the point " << *point << ", it's connected to no lines!"); 3656 return 0.; 3657 } 3658 3659 list<TesselPointList *> *ListOfClosedPaths = GetClosedPathsOfConnectedPoints(point->node); 3239 3660 list<TesselPointList *>::iterator ListAdvance = ListOfClosedPaths->begin(); 3240 3661 list<TesselPointList *>::iterator ListRunner = ListAdvance; 3241 3662 // TriangleMap::iterator NumberRunner = Candidates.begin(); 3242 3663 TesselPointList::iterator StartNode, MiddleNode, EndNode; 3243 double angle;3244 double smallestangle;3245 3664 Vector Point, Reference, OrthogonalVector; 3246 if (count > 2) { // less than three triangles, then nothing will be created 3247 class TesselPoint *TriangleCandidates[3]; 3248 count = 0; 3249 for (; ListRunner != ListOfClosedPaths->end(); ListRunner = ListAdvance) { // go through all closed paths 3250 if (ListAdvance != ListOfClosedPaths->end()) 3251 ListAdvance++; 3252 3253 connectedPath = *ListRunner; 3254 // re-create all triangles by going through connected points list 3255 LineList NewLines; 3256 for (; !connectedPath->empty();) { 3257 // search middle node with widest angle to next neighbours 3258 EndNode = connectedPath->end(); 3259 smallestangle = 0.; 3260 for (MiddleNode = connectedPath->begin(); MiddleNode != connectedPath->end(); MiddleNode++) { 3261 LOG(1, "INFO: MiddleNode is " << **MiddleNode << "."); 3262 // construct vectors to next and previous neighbour 3263 StartNode = MiddleNode; 3264 if (StartNode == connectedPath->begin()) 3265 StartNode = connectedPath->end(); 3266 StartNode--; 3267 //LOG(3, "INFO: StartNode is " << **StartNode << "."); 3268 Point = ((*StartNode)->getPosition()) - ((*MiddleNode)->getPosition()); 3269 StartNode = MiddleNode; 3270 StartNode++; 3271 if (StartNode == connectedPath->end()) 3272 StartNode = connectedPath->begin(); 3273 //LOG(3, "INFO: EndNode is " << **StartNode << "."); 3274 Reference = ((*StartNode)->getPosition()) - ((*MiddleNode)->getPosition()); 3275 OrthogonalVector = ((*MiddleNode)->getPosition()) - OldPoint; 3276 OrthogonalVector.MakeNormalTo(Reference); 3277 angle = GetAngle(Point, Reference, OrthogonalVector); 3278 //if (angle < M_PI) // no wrong-sided triangles, please? 3279 if (fabs(angle - M_PI) < fabs(smallestangle - M_PI)) { // get straightest angle (i.e. construct those triangles with smallest area first) 3280 smallestangle = angle; 3281 EndNode = MiddleNode; 3282 } 3283 } 3284 MiddleNode = EndNode; 3285 if (MiddleNode == connectedPath->end()) { 3286 ELOG(0, "CRITICAL: Could not find a smallest angle!"); 3287 performCriticalExit(); 3288 } 3289 StartNode = MiddleNode; 3290 if (StartNode == connectedPath->begin()) 3291 StartNode = connectedPath->end(); 3292 StartNode--; 3293 EndNode++; 3294 if (EndNode == connectedPath->end()) 3295 EndNode = connectedPath->begin(); 3296 LOG(2, "INFO: StartNode is " << **StartNode << "."); 3297 LOG(2, "INFO: MiddleNode is " << **MiddleNode << "."); 3298 LOG(2, "INFO: EndNode is " << **EndNode << "."); 3299 LOG(1, "INFO: Attempting to create triangle " << (*StartNode)->getName() << ", " << (*MiddleNode)->getName() << " and " << (*EndNode)->getName() << "."); 3300 TriangleCandidates[0] = *StartNode; 3301 TriangleCandidates[1] = *MiddleNode; 3302 TriangleCandidates[2] = *EndNode; 3303 triangle = GetPresentTriangle(TriangleCandidates); 3304 if (triangle != NULL) { 3305 ELOG(0, "New triangle already present, skipping!"); 3306 StartNode++; 3307 MiddleNode++; 3308 EndNode++; 3309 if (StartNode == connectedPath->end()) 3310 StartNode = connectedPath->begin(); 3311 if (MiddleNode == connectedPath->end()) 3312 MiddleNode = connectedPath->begin(); 3313 if (EndNode == connectedPath->end()) 3314 EndNode = connectedPath->begin(); 3315 continue; 3316 } 3317 LOG(3, "Adding new triangle points."); 3318 AddTesselationPoint(*StartNode, 0); 3319 AddTesselationPoint(*MiddleNode, 1); 3320 AddTesselationPoint(*EndNode, 2); 3321 LOG(3, "Adding new triangle lines."); 3322 AddTesselationLine(NULL, NULL, TPS[0], TPS[1], 0); 3323 AddTesselationLine(NULL, NULL, TPS[0], TPS[2], 1); 3324 NewLines.push_back(BLS[1]); 3325 AddTesselationLine(NULL, NULL, TPS[1], TPS[2], 2); 3326 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3327 BTS->GetNormalVector(NormalVector); 3328 AddTesselationTriangle(); 3329 // calculate volume summand as a general tetraeder 3330 volume += CalculateVolumeofGeneralTetraeder(TPS[0]->node->getPosition(), TPS[1]->node->getPosition(), TPS[2]->node->getPosition(), OldPoint); 3331 // advance number 3332 count++; 3333 3334 // prepare nodes for next triangle 3335 StartNode = EndNode; 3336 LOG(2, "Removing " << **MiddleNode << " from closed path, remaining points: " << connectedPath->size() << "."); 3337 connectedPath->remove(*MiddleNode); // remove the middle node (it is surrounded by triangles) 3338 if (connectedPath->size() == 2) { // we are done 3339 connectedPath->remove(*StartNode); // remove the start node 3340 connectedPath->remove(*EndNode); // remove the end node 3341 break; 3342 } else if (connectedPath->size() < 2) { // something's gone wrong! 3343 ELOG(0, "CRITICAL: There are only two endpoints left!"); 3344 performCriticalExit(); 3345 } else { 3346 MiddleNode = StartNode; 3347 MiddleNode++; 3348 if (MiddleNode == connectedPath->end()) 3349 MiddleNode = connectedPath->begin(); 3350 EndNode = MiddleNode; 3351 EndNode++; 3352 if (EndNode == connectedPath->end()) 3353 EndNode = connectedPath->begin(); 3354 } 3355 } 3356 // maximize the inner lines (we preferentially created lines with a huge angle, which is for the tesselation not wanted though useful for the closing) 3357 if (NewLines.size() > 1) { 3358 LineList::iterator Candidate; 3359 class BoundaryLineSet *OtherBase = NULL; 3360 double tmp, maxgain; 3361 do { 3362 maxgain = 0; 3363 for (LineList::iterator Runner = NewLines.begin(); Runner != NewLines.end(); Runner++) { 3364 tmp = PickFarthestofTwoBaselines(*Runner); 3365 if (maxgain < tmp) { 3366 maxgain = tmp; 3367 Candidate = Runner; 3368 } 3369 } 3370 if (maxgain != 0) { 3371 volume += maxgain; 3372 LOG(1, "Flipping baseline with highest volume" << **Candidate << "."); 3373 OtherBase = FlipBaseline(*Candidate); 3374 NewLines.erase(Candidate); 3375 NewLines.push_back(OtherBase); 3376 } 3377 } while (maxgain != 0.); 3378 } 3379 3380 ListOfClosedPaths->remove(connectedPath); 3381 delete (connectedPath); 3382 } 3383 LOG(1, "INFO: " << count << " triangles were created."); 3384 } else { 3385 while (!ListOfClosedPaths->empty()) { 3386 ListRunner = ListOfClosedPaths->begin(); 3387 connectedPath = *ListRunner; 3388 ListOfClosedPaths->remove(connectedPath); 3389 delete (connectedPath); 3390 } 3391 LOG(3, "DEBUG: No need to create any triangles."); 3665 for (; ListRunner != ListOfClosedPaths->end(); ListRunner = ListAdvance) { // go through all closed paths 3666 if (ListAdvance != ListOfClosedPaths->end()) 3667 ListAdvance++; 3668 3669 TesselPointList *connectedPath = *ListRunner; 3670 3671 if (CheckAllConcaveInPolygon(connectedPath, point)) { 3672 LOG(1, "INFO: ... point " << *point << " cannot be on convex envelope, all lines concave."); 3673 volume += RemovePointSurroundedByPolygon(connectedPath, point); 3674 } 3675 3676 ListOfClosedPaths->remove(connectedPath); 3677 delete (connectedPath); 3392 3678 } 3393 3679 delete (ListOfClosedPaths); 3394 3680 3395 LOG(1, "INFO: Removed volume is " << volume << "."); 3681 if (volume > 0.) 3682 LOG(1, "INFO: Removed volume is " << volume << "."); 3396 3683 3397 3684 return volume; … … 3437 3724 if (TrianglePoints[j] != NULL) { 3438 3725 for (FindLine = TrianglePoints[i]->lines.find(TrianglePoints[j]->node->getNr()); // is a multimap! 3439 (FindLine != TrianglePoints[i]->lines.end()) && (FindLine->first == TrianglePoints[j]->node->getNr()); FindLine++) {3726 (FindLine != TrianglePoints[i]->lines.end()) && (FindLine->first == TrianglePoints[j]->node->getNr()); FindLine++) { 3440 3727 for (FindTriangle = FindLine->second->triangles.begin(); FindTriangle != FindLine->second->triangles.end(); FindTriangle++) { 3441 3728 if (FindTriangle->second->IsPresentTupel(TrianglePoints)) { … … 3458 3745 break; 3459 3746 for (FindLine = TrianglePoints[(i + 1) % 3]->lines.find(TrianglePoints[(i + 2) % 3]->node->getNr()); // is a multimap! 3460 (FindLine != TrianglePoints[(i + 1) % 3]->lines.end()) && (FindLine->first == TrianglePoints[(i + 2) % 3]->node->getNr()); FindLine++) {3747 (FindLine != TrianglePoints[(i + 1) % 3]->lines.end()) && (FindLine->first == TrianglePoints[(i + 2) % 3]->node->getNr()); FindLine++) { 3461 3748 for (FindTriangle = FindLine->second->triangles.begin(); FindTriangle != FindLine->second->triangles.end(); FindTriangle++) { 3462 3749 if (FindTriangle->second->IsPresentTupel(TrianglePoints)) { … … 3487 3774 } 3488 3775 default: 3489 ELOG(0, "Number of wildcards is greater than 3, cannot happen!"); 3490 performCriticalExit(); 3776 ASSERT(0, "Tesselation::FindTriangles() - Number of wildcards is greater than 3, cannot happen!"); 3491 3777 break; 3492 3778 } … … 3514 3800 if (a->endpoints[lowerNra] < b->endpoints[lowerNrb]) 3515 3801 return true; 3516 else if (a->endpoints[lowerNra] > b->endpoints[lowerNrb]) 3517 return false; 3518 else { // both lower-numbered endpoints are the same ... 3519 if (a->endpoints[(lowerNra + 1) % 2] < b->endpoints[(lowerNrb + 1) % 2]) 3520 return true; 3521 else if (a->endpoints[(lowerNra + 1) % 2] > b->endpoints[(lowerNrb + 1) % 2]) 3802 else 3803 if (a->endpoints[lowerNra] > b->endpoints[lowerNrb]) 3522 3804 return false; 3523 } 3805 else { // both lower-numbered endpoints are the same ... 3806 if (a->endpoints[(lowerNra + 1) % 2] < b->endpoints[(lowerNrb + 1) % 2]) 3807 return true; 3808 else 3809 if (a->endpoints[(lowerNra + 1) % 2] > b->endpoints[(lowerNrb + 1) % 2]) 3810 return false; 3811 } 3524 3812 return false; 3525 3813 } … … 3542 3830 3543 3831 // sanity check 3544 if (LinesOnBoundary.empty()) {3545 ELOG(2, "FindAllDegeneratedTriangles() was called without any tesselation structure.");3546 return DegeneratedLines;3547 }3548 LineMap::iterator LineRunner1;3549 pair<UniqueLines::iterator, bool> tester;3832 if (LinesOnBoundary.empty()) { 3833 ELOG(2, "FindAllDegeneratedTriangles() was called without any tesselation structure."); 3834 return DegeneratedLines; 3835 } 3836 LineMap::iterator LineRunner1; 3837 pair<UniqueLines::iterator, bool> tester; 3550 3838 for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) { 3551 3839 tester = AllLines.insert(LineRunner1->second); … … 3564 3852 const LineMap::const_iterator Line2 = LinesOnBoundary.find((*it).second); 3565 3853 if (Line1 != LinesOnBoundary.end() && Line2 != LinesOnBoundary.end()) 3566 3854 LOG(3, "DEBUG: " << *Line1->second << " => " << *Line2->second); 3567 3855 else 3568 3856 ELOG(1, "Either " << (*it).first << " or " << (*it).second << " are not in LinesOnBoundary!"); 3569 3857 } 3570 3858 … … 3598 3886 for (TriangleRunner2 = line2->triangles.begin(); TriangleRunner2 != line2->triangles.end(); ++TriangleRunner2) { 3599 3887 if ((TriangleRunner1->second != TriangleRunner2->second) && (TriangleRunner1->second->IsPresentTupel(TriangleRunner2->second))) { 3600 DegeneratedTriangles->insert(pair<int, int> 3601 DegeneratedTriangles->insert(pair<int, int> 3888 DegeneratedTriangles->insert(pair<int, int>(TriangleRunner1->second->Nr, TriangleRunner2->second->Nr)); 3889 DegeneratedTriangles->insert(pair<int, int>(TriangleRunner2->second->Nr, TriangleRunner1->second->Nr)); 3602 3890 } 3603 3891 } … … 3626 3914 3627 3915 // iterate over all degenerated triangles 3628 for (IndexToIndex::iterator TriangleKeyRunner = DegeneratedTriangles->begin(); !DegeneratedTriangles->empty(); TriangleKeyRunner = DegeneratedTriangles->begin()) { 3916 for (IndexToIndex::iterator TriangleKeyRunner = DegeneratedTriangles->begin(); 3917 !DegeneratedTriangles->empty(); 3918 TriangleKeyRunner = DegeneratedTriangles->begin()) { 3629 3919 LOG(3, "DEBUG: Checking presence of triangles " << TriangleKeyRunner->first << " and " << TriangleKeyRunner->second << "."); 3630 3920 // both ways are stored in the map, only use one … … 3667 3957 // OtherpartnerTriangle = TriangleRunner->second; 3668 3958 // } 3669 /// interchanges their lines so that triangle->lines[i] == partnerTriangle->lines[j]3670 // the line of triangle receives the degenerated ones3671 triangle->lines[i]->triangles.erase(Othertriangle->Nr);3959 /// interchanges their lines so that triangle->lines[i] == partnerTriangle->lines[j] 3960 // the line of triangle receives the degenerated ones 3961 triangle->lines[i]->triangles.erase(Othertriangle->Nr); 3672 3962 triangle->lines[i]->triangles.insert(TrianglePair(partnerTriangle->Nr, partnerTriangle)); 3673 3963 for (int k = 0; k < 3; k++) … … 3683 3973 3684 3974 // erase the pair 3685 count += (int) 3975 count += (int)DegeneratedTriangles->erase(triangle->Nr); 3686 3976 LOG(4, "DEBUG: RemoveDegeneratedTriangles() removes triangle " << *triangle << "."); 3687 3977 RemoveTesselationTriangle(triangle); 3688 count += (int) 3978 count += (int)DegeneratedTriangles->erase(partnerTriangle->Nr); 3689 3979 LOG(4, "DEBUG: RemoveDegeneratedTriangles() removes triangle " << *partnerTriangle << "."); 3690 3980 RemoveTesselationTriangle(partnerTriangle); 3691 3981 } else { 3692 3982 LOG(4, "DEBUG: RemoveDegeneratedTriangles() does not remove triangle " << *triangle << " and its partner " << *partnerTriangle << " because it is essential for at" << " least one of the endpoints to be kept in the tesselation structure."); 3983 // we need to remove them from the list nonetheless 3984 DegeneratedTriangles->erase(triangle->Nr); 3985 DegeneratedTriangles->erase(partnerTriangle->Nr); 3693 3986 } 3694 3987 } … … 3734 4027 class BoundaryLineSet *BestLine = NULL; 3735 4028 for (LineMap::iterator Runner = NearestBoundaryPoint->lines.begin(); Runner != NearestBoundaryPoint->lines.end(); Runner++) { 3736 BaseLine = (Runner->second->endpoints[0]->node->getPosition()) - 3737 (Runner->second->endpoints[1]->node->getPosition()); 3738 CenterToPoint = 0.5 * ((Runner->second->endpoints[0]->node->getPosition()) + 3739 (Runner->second->endpoints[1]->node->getPosition())); 4029 BaseLine = (Runner->second->endpoints[0]->node->getPosition()) - (Runner->second->endpoints[1]->node->getPosition()); 4030 CenterToPoint = 0.5 * ((Runner->second->endpoints[0]->node->getPosition()) + (Runner->second->endpoints[1]->node->getPosition())); 3740 4031 CenterToPoint -= (point->getPosition()); 3741 4032 angle = CenterToPoint.Angle(BaseLine); 3742 if (fabs(angle - M_PI /2.) < fabs(BestAngle - M_PI/2.)) {4033 if (fabs(angle - M_PI / 2.) < fabs(BestAngle - M_PI / 2.)) { 3743 4034 BestAngle = angle; 3744 4035 BestLine = Runner->second; … … 3789 4080 for (int i = 0; i < 3; i++) { // look for the same line as BestLine (only it's its degenerated companion) 3790 4081 if ((BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[0])) && (BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[1]))) { 3791 if (BestLine == BTS->lines[i]) { 3792 ELOG(0, "BestLine is same as found line, something's wrong here!"); 3793 performCriticalExit(); 3794 } 3795 BTS->lines[i]->triangles.insert(pair<int, class BoundaryTriangleSet *> (TempTriangle->Nr, TempTriangle)); 4082 ASSERT(BestLine != BTS->lines[i], std::string("Tesselation::AddBoundaryPointByDegeneratedTriangle() - ") + std::string("BestLine is same as found line, something's wrong here!")); 4083 BTS->lines[i]->triangles.insert(pair<int, class BoundaryTriangleSet *>(TempTriangle->Nr, TempTriangle)); 3796 4084 TempTriangle->lines[nr] = BTS->lines[i]; 3797 4085 break; … … 3815 4103 if (LastTriangle != NULL) { 3816 4104 stringstream sstr; 3817 sstr << "-" << TrianglesOnBoundary.size() << "-" << LastTriangle->getEndpointName(0) << "_" << LastTriangle->getEndpointName(1) << "_" << LastTriangle->getEndpointName(2);4105 sstr << "-" << TrianglesOnBoundary.size() << "-" << LastTriangle->getEndpointName(0) << "_" << LastTriangle->getEndpointName(1) << "_" << LastTriangle->getEndpointName(2); 3818 4106 NumberName = sstr.str(); 3819 4107 if (DoTecplotOutput) { … … 3857 4145 if (s1->endpoints.size() < s2->endpoints.size()) 3858 4146 return true; 3859 else if (s1->endpoints.size() > s2->endpoints.size()) 3860 return false; 3861 else { // equality of number of endpoints 3862 PointSet::const_iterator Walker1 = s1->endpoints.begin(); 3863 PointSet::const_iterator Walker2 = s2->endpoints.begin(); 3864 while ((Walker1 != s1->endpoints.end()) || (Walker2 != s2->endpoints.end())) { 3865 if ((*Walker1)->Nr < (*Walker2)->Nr) 3866 return true; 3867 else if ((*Walker1)->Nr > (*Walker2)->Nr) 3868 return false; 3869 Walker1++; 3870 Walker2++; 4147 else 4148 if (s1->endpoints.size() > s2->endpoints.size()) 4149 return false; 4150 else { // equality of number of endpoints 4151 PointSet::const_iterator Walker1 = s1->endpoints.begin(); 4152 PointSet::const_iterator Walker2 = s2->endpoints.begin(); 4153 while ((Walker1 != s1->endpoints.end()) || (Walker2 != s2->endpoints.end())) { 4154 if ((*Walker1)->Nr < (*Walker2)->Nr) 4155 return true; 4156 else 4157 if ((*Walker1)->Nr > (*Walker2)->Nr) 4158 return false; 4159 Walker1++; 4160 Walker2++; 4161 } 4162 return false; 3871 4163 } 3872 return false;3873 }3874 4164 } 3875 4165 }; … … 3896 4186 for (TriangleMap::const_iterator TriangleRunner = (LineRunner->second)->triangles.begin(); TriangleRunner != (LineRunner->second)->triangles.end(); TriangleRunner++) { 3897 4187 if (DegeneratedTriangles->find(TriangleRunner->second->Nr) == DegeneratedTriangles->end()) { 3898 TriangleInsertionTester = TriangleVectors.insert(pair<int, Vector *> 4188 TriangleInsertionTester = TriangleVectors.insert(pair<int, Vector *>((TriangleRunner->second)->Nr, &((TriangleRunner->second)->NormalVector))); 3899 4189 if (TriangleInsertionTester.second) 3900 4190 LOG(5, "DEBUG: Adding triangle " << *(TriangleRunner->second) << " to triangles to check-list."); … … 3909 4199 if (VectorWalker != VectorRunner) { // skip equals 3910 4200 const double SCP = VectorWalker->second->ScalarProduct(*VectorRunner->second); // ScalarProduct should result in -1. for degenerated triangles 3911 LOG(4, "DEBUG: Checking " << * VectorWalker->second << " against " << *VectorRunner->second<< ": " << SCP);4201 LOG(4, "DEBUG: Checking " << *(VectorWalker->second) << " against " << *(VectorRunner->second) << ": " << SCP); 3912 4202 if (fabs(SCP + 1.) < ParallelEpsilon) { 3913 4203 InsertionTester = EndpointCandidateList.insert((Runner->second)); … … 3991 4281 // The Problem is probably due to two degenerated polygons being connected by a bridging, non-degenerated polygon, as somehow one node has 3992 4282 // connections to either polygon ... 3993 if (T->size() % 2 != 0) { 3994 ELOG(0, " degenerated polygon contains an odd number of triangles, probably contains bridging non-degenerated ones, too!"); 3995 performCriticalExit(); 3996 } 4283 ASSERT(T->size() % 2 == 0, std::string("Tesselation::CorrectAllDegeneratedPolygons() - ") + std::string(" degenerated polygon contains an odd number of triangles,") + std::string(" probably contains bridging non-degenerated ones, too!")); 3997 4284 TriangleSet::iterator TriangleWalker = T->begin(); // is the inner iterator 3998 4285 /// 4a. Get NormalVector for one side (this is "front")
Note:
See TracChangeset
for help on using the changeset viewer.