Changes in src/Tesselation/tesselation.cpp [e2396e:8592c9]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tesselation/tesselation.cpp
re2396e r8592c9 35 35 #include "CodePatterns/MemDebug.hpp" 36 36 37 #include <algorithm>38 #include <boost/foreach.hpp>39 37 #include <fstream> 40 38 #include <iomanip> 41 #include <iterator>42 39 #include <sstream> 43 40 … … 69 66 class molecule; 70 67 71 const char *TecplotSuffix =".dat";72 const char *Raster3DSuffix =".r3d";73 const char *VRMLSUffix =".wrl";74 75 const double ParallelEpsilon =1e-3;68 const char *TecplotSuffix=".dat"; 69 const char *Raster3DSuffix=".r3d"; 70 const char *VRMLSUffix=".wrl"; 71 72 const double ParallelEpsilon=1e-3; 76 73 const double Tesselation::HULLEPSILON = 1e-9; 77 74 … … 79 76 */ 80 77 Tesselation::Tesselation() : 81 PointsOnBoundaryCount(0), LinesOnBoundaryCount(0), TrianglesOnBoundaryCount(0), LastTriangle(NULL), TriangleFilesWritten(0), InternalPointer(PointsOnBoundary.begin()) 78 PointsOnBoundaryCount(0), 79 LinesOnBoundaryCount(0), 80 TrianglesOnBoundaryCount(0), 81 LastTriangle(NULL), 82 TriangleFilesWritten(0), 83 InternalPointer(PointsOnBoundary.begin()) 82 84 { 83 85 //Info FunctionInfo(__func__); … … 111 113 { 112 114 // create linkedcell 113 LinkedCell_deprecated *LinkedList = new LinkedCell_deprecated(cloud, 2. *SPHERERADIUS);114 115 116 117 118 119 for (size_t i = 0; i < 3;++i, cloud.GoToNext())115 LinkedCell_deprecated *LinkedList = new LinkedCell_deprecated(cloud, 2.*SPHERERADIUS); 116 117 // check for at least three points 118 { 119 bool ThreePointsFound = true; 120 cloud.GoToFirst(); 121 for (size_t i=0;i<3;++i, cloud.GoToNext()) 120 122 ThreePointsFound &= (!cloud.IsEnd()); 121 123 cloud.GoToFirst(); … … 124 126 return; 125 127 } 126 127 128 128 } 129 130 // find a starting triangle 129 131 FindStartingTriangle(SPHERERADIUS, LinkedList); 130 132 … … 140 142 //the line is there, so there is a triangle, but only one. 141 143 const bool TesselationFailFlag = FindNextSuitableTriangle(*baseline, *T, SPHERERADIUS, LinkedList); 142 ASSERT(TesselationFailFlag, "Tesselation::operator() - no suitable candidate triangle found."); 144 ASSERT( TesselationFailFlag, 145 "Tesselation::operator() - no suitable candidate triangle found."); 143 146 } 144 147 } 145 148 146 149 // 2b. search for smallest ShortestAngle among all candidates 147 double ShortestAngle = 4. *M_PI;150 double ShortestAngle = 4.*M_PI; 148 151 for (CandidateMap::iterator Runner = OpenLines.begin(); Runner != OpenLines.end(); Runner++) { 149 152 if (Runner->second->ShortestAngle < ShortestAngle) { … … 152 155 } 153 156 } 154 if ((ShortestAngle == 4. *M_PI) || (baseline->pointlist.empty()))157 if ((ShortestAngle == 4.*M_PI) || (baseline->pointlist.empty())) 155 158 OneLoopWithoutSuccessFlag = false; 156 159 else { … … 158 161 } 159 162 } 160 161 delete LinkedList;162 163 } 163 164 … … 169 170 double Tesselation::getVolumeOfConvexEnvelope(const bool IsAngstroem) const 170 171 { 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 } 172 double volume = 0.; 173 Vector x; 174 Vector y; 179 175 180 176 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 181 double volume = 0.; 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."); 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."); 194 193 195 194 return volume; … … 208 207 209 208 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 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."); 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."); 216 218 217 219 return surfacearea; 218 220 } 221 219 222 220 223 /** Gueses first starting triangle of the convex envelope. … … 248 251 tmp = B->second->node->DistanceSquared(C->second->node->getPosition()); 249 252 distance += tmp * tmp; 250 DistanceMMap.insert(DistanceMultiMapPair(distance, pair<PointMap::iterator, PointMap::iterator> (B, C)));253 DistanceMMap.insert(DistanceMultiMapPair(distance, pair<PointMap::iterator, PointMap::iterator> (B, C))); 251 254 } 252 255 } … … 268 271 // 2. next, we have to check whether all points reside on only one side of the triangle 269 272 // 3. construct plane vector 270 PlaneVector = Plane(A->second->node->getPosition(), baseline->second.first->second->node->getPosition(), baseline->second.second->second->node->getPosition()).getNormal(); 273 PlaneVector = Plane(A->second->node->getPosition(), 274 baseline->second.first->second->node->getPosition(), 275 baseline->second.second->second->node->getPosition()).getNormal(); 271 276 LOG(2, "Plane vector of candidate triangle is " << PlaneVector); 272 277 // 4. loop over all points … … 383 388 // prepare some auxiliary vectors 384 389 Vector BaseLineCenter, BaseLine; 385 BaseLineCenter = 0.5 * ((baseline->second->endpoints[0]->node->getPosition()) + (baseline->second->endpoints[1]->node->getPosition())); 390 BaseLineCenter = 0.5 * ((baseline->second->endpoints[0]->node->getPosition()) + 391 (baseline->second->endpoints[1]->node->getPosition())); 386 392 BaseLine = (baseline->second->endpoints[0]->node->getPosition()) - (baseline->second->endpoints[1]->node->getPosition()); 387 393 … … 401 407 // vector in propagation direction (out of triangle) 402 408 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 403 PropagationVector = Plane(BaseLine, NormalVector, 409 PropagationVector = Plane(BaseLine, NormalVector,0).getNormal(); 404 410 TempVector = CenterVector - (baseline->second->endpoints[0]->node->getPosition()); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 405 411 //LOG(0, "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "."); … … 454 460 // in case NOT both were found, create virtually this triangle, get its normal vector, calculate angle 455 461 flag = true; 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())); 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())); 458 468 TempVector -= (*Center); 459 469 // make it always point outward … … 467 477 winner = target; 468 478 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."); 494 } else 495 LOG(5, "DEBUG: Keeping old winner " << *winner->second->node << " due to smaller angle to propagation direction."); 469 496 } 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."); 487 } else 488 LOG(5, "DEBUG: Keeping old winner " << *winner->second->node << " due to smaller angle between normal vectors."); 497 LOG(5, "DEBUG: Keeping old winner " << *winner->second->node << " due to smaller angle between normal vectors."); 489 498 } 490 499 } // end of loop over all boundary points … … 553 562 554 563 cloud.GoToFirst(); 555 PointCloudAdaptor< Tesselation, MapValueIterator<Tesselation::iterator> > newcloud(this, cloud.GetName());564 PointCloudAdaptor< Tesselation, MapValueIterator<Tesselation::iterator> > newcloud(this, cloud.GetName()); 556 565 BoundaryPoints = new LinkedCell_deprecated(newcloud, 5.); 557 566 while (!cloud.IsEnd()) { // we only have to go once through all points, as boundary can become only bigger … … 720 729 * @param *b second endpoint 721 730 * @param n index of Tesselation::BLS giving the line with both endpoints 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) 731 */ 732 void Tesselation::AddTesselationLine(const Vector * const OptCenter, const BoundaryPointSet * const candidate, class BoundaryPointSet *a, class BoundaryPointSet *b, const int n) 725 733 { 726 734 bool insertNewLine = true; … … 738 746 if (FindLine->second->triangles.size() == 1) { 739 747 CandidateMap::iterator Finder = OpenLines.find(FindLine->second); 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."); 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 << "."); 746 756 insertNewLine = false; 747 757 WinningLine = FindLine->second; 758 break; 759 } else { 760 LOG(5, "REJECT: Candidate " << *(*CandidateChecker) << "'s center " << Finder->second->OptCenter << " does not match desired on " << *OptCenter << "."); 748 761 } 749 // get open line750 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 matches752 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;764 762 } 765 763 } … … 772 770 AddExistingTesselationTriangleLine(WinningLine, n); 773 771 } 774 775 return insertNewLine;776 772 } 777 773 ; … … 798 794 // also add to open lines 799 795 CandidateForTesselation *CFT = new CandidateForTesselation(BLS[n]); 800 OpenLines.insert(pair<BoundaryLineSet *, CandidateForTesselation *> (BLS[n], CFT));796 OpenLines.insert(pair<BoundaryLineSet *, CandidateForTesselation *> (BLS[n], CFT)); 801 797 } 802 798 ; … … 887 883 } else { 888 884 output << "still attached to another triangle: "; 885 OpenLines.insert(pair<BoundaryLineSet *, CandidateForTesselation *> (triangle->lines[i], NULL)); 889 886 for (TriangleMap::iterator TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); TriangleRunner++) 890 887 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));892 888 } 893 889 LOG(3, "DEBUG: " << output.str()); … … 923 919 else 924 920 Numbers[1] = -1; 925 926 // erase from OpenLines if present927 {928 CandidateMap::iterator openlineiter = OpenLines.find(line);929 if (openlineiter != OpenLines.end())930 OpenLines.erase(openlineiter);931 }932 921 933 922 for (int i = 0; i < 2; i++) { … … 948 937 LOG(4, "DEBUG: " << *line->endpoints[i] << " has no more lines it's attached to, erasing."); 949 938 RemoveTesselationPoint(line->endpoints[i]); 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 } 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 } 958 946 line->endpoints[i] = NULL; // free'd or not: disconnect 959 947 } else … … 997 985 //Info FunctionInfo(__func__); 998 986 999 LOG(3, "DEBUG: Checking degeneracy bywhether sphere contains no others points ...");987 LOG(3, "DEBUG: Checking whether sphere contains no others points ..."); 1000 988 bool flag = true; 1001 989 … … 1004 992 TesselPointList *ListofPoints = LC->GetPointsInsideSphere(RADIUS, &CandidateLine.OtherOptCenter); 1005 993 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 << ":"); 994 LOG(3, "DEBUG: The following atoms are inside sphere at " << CandidateLine.OtherOptCenter << ":"); 1008 995 for (TesselPointList::const_iterator Runner = ListofPoints->begin(); Runner != ListofPoints->end(); ++Runner) 1009 LOG( 4, "DEBUG: " << *(*Runner) << " with distance " << (*Runner)->distance(CandidateLine.OtherOptCenter) << ".");996 LOG(3, "DEBUG: " << *(*Runner) << " with distance " << (*Runner)->distance(CandidateLine.OtherOptCenter) << "."); 1010 997 1011 998 // remove triangles's endpoints … … 1021 1008 LOG(3, "DEBUG: CheckDegeneracy: There are still " << ListofPoints->size() << " points inside the sphere."); 1022 1009 flag = false; 1023 LOG( 4, "DEBUG: External atoms inside of sphere at " << CandidateLine.OtherOptCenter << ":");1010 LOG(3, "DEBUG: External atoms inside of sphere at " << CandidateLine.OtherOptCenter << ":"); 1024 1011 for (TesselPointList::const_iterator Runner = ListofPoints->begin(); Runner != ListofPoints->end(); ++Runner) 1025 LOG( 4, "DEBUG: " << *(*Runner) << " with distance " << (*Runner)->distance(CandidateLine.OtherOptCenter) << ".");1026 } 1027 delete ListofPoints;1012 LOG(3, "DEBUG: " << *(*Runner) << " with distance " << (*Runner)->distance(CandidateLine.OtherOptCenter) << "."); 1013 } 1014 delete (ListofPoints); 1028 1015 1029 1016 return flag; … … 1168 1155 1169 1156 // 1. searching topmost point with respect to each axis 1170 LOG(2, "INFO: Searching for topmost pointer from each axis.");1171 1157 for (int i = 0; i < NDIM; i++) { // each axis 1172 1158 LC->n[i] = LC->N[i] - 1; // current axis is topmost cell … … 1190 1176 } 1191 1177 1192 if (DoLog( 3)) {1178 if (DoLog(1)) { 1193 1179 std::stringstream output; 1194 1180 output << "Found maximum coordinates: "; … … 1204 1190 BaseLine = new BoundaryLineSet(); 1205 1191 BaseLine->endpoints[0] = new BoundaryPointSet(MaxPoint[k]); 1206 LOG(2, " INFO: Coordinates of start node at " << *BaseLine->endpoints[0]->node << ".");1192 LOG(2, "DEBUG: Coordinates of start node at " << *BaseLine->endpoints[0]->node << "."); 1207 1193 1208 1194 double ShortestAngle; … … 1217 1203 } 1218 1204 BaseLine->endpoints[1] = new BoundaryPointSet(Temporary); 1219 LOG( 2, "INFO: Second node is at " << *Temporary << ".");1205 LOG(1, "INFO: Second node is at " << *Temporary << "."); 1220 1206 1221 1207 // construct center of circle 1222 1208 CircleCenter = 0.5 * ((BaseLine->endpoints[0]->node->getPosition()) + (BaseLine->endpoints[1]->node->getPosition())); 1223 LOG( 4, "DEBUG: CircleCenter is at " << CircleCenter << ".");1209 LOG(1, "INFO: CircleCenter is at " << CircleCenter << "."); 1224 1210 1225 1211 // construct normal vector of circle 1226 1212 CirclePlaneNormal = (BaseLine->endpoints[0]->node->getPosition()) - (BaseLine->endpoints[1]->node->getPosition()); 1227 LOG( 4, "DEBUG: CirclePlaneNormal is at " << CirclePlaneNormal << ".");1213 LOG(1, "INFO: CirclePlaneNormal is at " << CirclePlaneNormal << "."); 1228 1214 1229 1215 double radius = CirclePlaneNormal.NormSquared(); … … 1232 1218 NormalVector.ProjectOntoPlane(CirclePlaneNormal); 1233 1219 NormalVector.Normalize(); 1234 LOG( 4, "DEBUG: NormalVector is at " << NormalVector << ".");1220 LOG(1, "INFO: NormalVector is at " << NormalVector << "."); 1235 1221 ShortestAngle = 2. * M_PI; // This will indicate the quadrant. 1236 1222 1237 SphereCenter = (CircleRadius * NormalVector) + CircleCenter;1223 SphereCenter = (CircleRadius * NormalVector) + CircleCenter; 1238 1224 // Now, NormalVector and SphereCenter are two orthonormalized vectors in the plane defined by CirclePlaneNormal (not normalized) 1239 1225 1240 1226 // look in one direction of baseline for initial candidate 1241 1227 try { 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 << "."); 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 << "."); 1245 1232 delete BaseLine; 1246 1233 continue; … … 1248 1235 1249 1236 // adding point 1 and point 2 and add the line between them 1250 LOG( 3, "DEBUG: Found second point is at " << *BaseLine->endpoints[1]->node << ".");1237 LOG(2, "DEBUG: Found second point is at " << *BaseLine->endpoints[1]->node << "."); 1251 1238 1252 1239 //LOG(1, "INFO: OldSphereCenter is at " << helper << "."); … … 1257 1244 for (TesselPointList::iterator it = OptCandidates.pointlist.begin(); it != OptCandidates.pointlist.end(); it++) 1258 1245 output << *(*it); 1259 LOG( 3, "DEBUG: List of third Points is: " << output.str());1246 LOG(2, "DEBUG: List of third Points is: " << output.str()); 1260 1247 } 1261 1248 if (!OptCandidates.pointlist.empty()) { … … 1419 1406 // return result; 1420 1407 //}; 1408 1421 1409 /** This function finds a triangle to a line, adjacent to an existing one. 1422 1410 * @param out output stream for debugging … … 1450 1438 1451 1439 // construct center of circle 1452 CircleCenter = 0.5 * ((CandidateLine.BaseLine->endpoints[0]->node->getPosition()) + (CandidateLine.BaseLine->endpoints[1]->node->getPosition())); 1440 CircleCenter = 0.5 * ((CandidateLine.BaseLine->endpoints[0]->node->getPosition()) + 1441 (CandidateLine.BaseLine->endpoints[1]->node->getPosition())); 1453 1442 1454 1443 // construct normal vector of circle 1455 CirclePlaneNormal = (CandidateLine.BaseLine->endpoints[0]->node->getPosition()) - (CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 1444 CirclePlaneNormal = (CandidateLine.BaseLine->endpoints[0]->node->getPosition()) - 1445 (CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 1456 1446 1457 1447 // calculate squared radius of circle … … 1463 1453 CircleRadius = RADIUS * RADIUS - radius / 4.; 1464 1454 CirclePlaneNormal.Normalize(); 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 << ".");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 << "."); 1468 1458 1469 1459 // construct SearchDirection and an "outward pointer" 1470 SearchDirection = Plane(RelativeSphereCenter, CirclePlaneNormal, 1460 SearchDirection = Plane(RelativeSphereCenter, CirclePlaneNormal,0).getNormal(); 1471 1461 helper = CircleCenter - (ThirdPoint->node->getPosition()); 1472 if (helper.ScalarProduct(SearchDirection) < -HULLEPSILON) 1462 if (helper.ScalarProduct(SearchDirection) < -HULLEPSILON)// ohoh, SearchDirection points inwards! 1473 1463 SearchDirection.Scale(-1.); 1474 LOG( 4, "DEBUG: SearchDirection is " << SearchDirection << ".");1464 LOG(3, "DEBUG: SearchDirection is " << SearchDirection << "."); 1475 1465 if (fabs(RelativeSphereCenter.ScalarProduct(SearchDirection)) > HULLEPSILON) { 1476 1466 // rotated the wrong way! … … 1482 1472 1483 1473 } else { 1484 LOG( 4, "DEBUG: Circumcircle for base line " << *CandidateLine.BaseLine << " and base triangle " << T << " is too big!");1474 LOG(3, "DEBUG: Circumcircle for base line " << *CandidateLine.BaseLine << " and base triangle " << T << " is too big!"); 1485 1475 } 1486 1476 … … 1515 1505 baseline = Runner->second; 1516 1506 if (baseline->pointlist.empty()) { 1517 ASSERT((baseline->BaseLine->triangles.size() == 1), 1507 ASSERT((baseline->BaseLine->triangles.size() == 1),"Open line without exactly one attached triangle"); 1518 1508 T = (((baseline->BaseLine->triangles.begin()))->second); 1519 1509 LOG(4, "DEBUG: Finding best candidate for open line " << *baseline->BaseLine << " of triangle " << *T); … … 1548 1538 TesselPointList *connectedClosestPoints = GetCircleOfSetOfPoints(&SetOfNeighbours, TurningPoint, CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 1549 1539 1550 if (DoLog(3)){1540 { 1551 1541 std::stringstream output; 1552 1542 for (TesselPointList::iterator TesselRunner = connectedClosestPoints->begin(); TesselRunner != connectedClosestPoints->end(); ++TesselRunner) 1553 1543 output << **TesselRunner; 1554 LOG(3, "DEBUG: List of Candidates for Turning Point " << *TurningPoint << ":" << output.str());1544 LOG(3, "DEBUG: List of Candidates for Turning Point " << *TurningPoint << ":"); 1555 1545 } 1556 1546 … … 1593 1583 } 1594 1584 delete (connectedClosestPoints); 1595 } 1596 ; 1585 }; 1597 1586 1598 1587 /** for polygons (multiple candidates for a baseline) sets internal edges to the correct next candidate. … … 1614 1603 else { 1615 1604 LOG(4, "DEBUG: line " << *(FindLine->second) << " is open with no candidate, setting to next Sprinter" << (*Sprinter)); 1616 Finder->second->T = BTS; // is last triangle1605 Finder->second->T = BTS; // is last triangle 1617 1606 Finder->second->pointlist.push_back(Sprinter); 1618 1607 Finder->second->ShortestAngle = 0.; … … 1621 1610 } 1622 1611 } 1623 } 1624 ; 1612 }; 1625 1613 1626 1614 /** If a given \a *triangle is degenerated, this adds both sides. … … 1658 1646 // give some verbose output about the whole procedure 1659 1647 if (CandidateLine.T != NULL) 1660 LOG(2, " INFO: --> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << ", from " << *CandidateLine.T << " and angle " << CandidateLine.ShortestAngle << ".");1648 LOG(2, "DEBUG: --> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << ", from " << *CandidateLine.T << " and angle " << CandidateLine.ShortestAngle << "."); 1661 1649 else 1662 LOG(2, " INFO: --> New starting triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " and no top triangle.");1650 LOG(2, "DEBUG: --> New starting triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " and no top triangle."); 1663 1651 triangle = BTS; 1664 1652 … … 1744 1732 ; 1745 1733 1746 bool Tesselation::isConvex() const1747 {1748 bool status = true;1749 // go through all lines on boundary1750 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 1760 1734 /** Checks whether the quadragon of the two triangles connect to \a *Base is convex. 1761 1735 * We look whether the closest point on \a *Base with respect to the other baseline is outside … … 1894 1868 } 1895 1869 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { 1896 1870 LOG(4, "DEBUG: Adding NormalVector " << runner->second->NormalVector << " of triangle " << *(runner->second) << "."); 1897 1871 BaseLineNormal += (runner->second->NormalVector); 1898 1872 } … … 1923 1897 class BoundaryLineSet *OldLines[4], *NewLine; 1924 1898 class BoundaryPointSet *OldPoints[2]; 1925 Vector BaseLineNormal[2]; 1926 Vector OtherEndpoint[2]; // fourth point to either triangle 1899 Vector BaseLineNormal; 1927 1900 int OldTriangleNrs[2], OldBaseLineNr; 1928 1901 int i, m; 1929 1902 1930 1903 // calculate NormalVector for later use 1904 BaseLineNormal.Zero(); 1931 1905 if (Base->triangles.size() < 2) { 1932 1906 ELOG(1, "Less than two triangles are attached to this baseline!"); 1933 1907 return NULL; 1934 1908 } 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 } 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() 1945 1914 1946 1915 // get the two triangles … … 1972 1941 1973 1942 // index OldLines and OldPoints 1974 // note that oldlines[0,1] belong to first triangle and hence first normal1975 // vector and oldlines[2,3] belong to second triangle and its normal vector1976 1943 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) 1977 1944 for (int j = 0; j < 3; j++) // all of their endpoints and baselines … … 1983 1950 OldPoints[m++] = runner->second->endpoints[j]; 1984 1951 1985 Vector BasePoints[2]; // endpoints of Base1986 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 }1993 1952 // check whether everything is in place to create new lines and triangles 1994 1953 if (i < 4) { … … 2006 1965 return NULL; 2007 1966 } 2008 2009 // construct plane of first triangle for calculating normal vectors later2010 const Plane triangleplane = Base->triangles.begin()->second->getPlane();2011 // get fourth point projected down onto this plane2012 const Vector Intersection = triangleplane.getClosestPoint(OtherEndpoint[0]);2013 1967 2014 1968 // remove triangles and baseline removes itself … … 2017 1971 m = 0; 2018 1972 // first obtain all triangle to delete ... (otherwise we pull the carpet (Base) from under the for-loop's feet) 2019 list <BoundaryTriangleSet *> TrianglesOfBase;1973 list <BoundaryTriangleSet *> TrianglesOfBase; 2020 1974 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); ++runner) 2021 1975 TrianglesOfBase.push_back(runner->second); 2022 1976 // .. then delete each triangle (which deletes the line as well) 2023 for (list <BoundaryTriangleSet *>::iterator runner = TrianglesOfBase.begin(); !TrianglesOfBase.empty(); runner = TrianglesOfBase.begin()) {1977 for (list <BoundaryTriangleSet *>::iterator runner = TrianglesOfBase.begin(); !TrianglesOfBase.empty(); runner = TrianglesOfBase.begin()) { 2024 1978 LOG(3, "DEBUG: Deleting triangle " << *(*runner) << "."); 2025 1979 OldTriangleNrs[m++] = (*runner)->Nr; … … 2034 1988 LinesOnBoundary.insert(LinePair(OldBaseLineNr, NewLine)); // no need for check for unique insertion as NewLine is definitely a new one 2035 1989 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 fourth2039 // endpoint is with respect to the joining boundary line on one side or on2040 // the other with respect to the endpoint of the plane triangle that is not2041 // contained in the joining boundary line.2042 1990 2043 1991 // construct new triangles with flipped baseline … … 2052 2000 BLS[2] = NewLine; 2053 2001 BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[0]); 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 } 2002 BTS->GetNormalVector(BaseLineNormal); 2074 2003 AddTesselationTriangle(OldTriangleNrs[0]); 2075 2004 LOG(3, "DEBUG: Created new triangle " << *BTS << "."); … … 2079 2008 BLS[2] = NewLine; 2080 2009 BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[1]); 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 } 2010 BTS->GetNormalVector(BaseLineNormal); 2101 2011 AddTesselationTriangle(OldTriangleNrs[1]); 2102 2012 LOG(3, "DEBUG: Created new triangle " << *BTS << "."); … … 2245 2155 TesselPoint *Candidate = NULL; 2246 2156 2247 LOG( 4, "DEBUG: NormalVector of BaseTriangle is " << NormalVector << ".");2157 LOG(3, "DEBUG: NormalVector of BaseTriangle is " << NormalVector << "."); 2248 2158 2249 2159 // copy old center … … 2253 2163 2254 2164 // construct center of circle 2255 CircleCenter = 0.5 * ((CandidateLine.BaseLine->endpoints[0]->node->getPosition()) + (CandidateLine.BaseLine->endpoints[1]->node->getPosition())); 2165 CircleCenter = 0.5 * ((CandidateLine.BaseLine->endpoints[0]->node->getPosition()) + 2166 (CandidateLine.BaseLine->endpoints[1]->node->getPosition())); 2256 2167 2257 2168 // construct normal vector of circle 2258 CirclePlaneNormal = (CandidateLine.BaseLine->endpoints[0]->node->getPosition()) - (CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 2169 CirclePlaneNormal = (CandidateLine.BaseLine->endpoints[0]->node->getPosition()) - 2170 (CandidateLine.BaseLine->endpoints[1]->node->getPosition()); 2259 2171 2260 2172 RelativeOldSphereCenter = OldSphereCenter - CircleCenter; … … 2265 2177 CircleRadius = RADIUS * RADIUS - radius; 2266 2178 CirclePlaneNormal.Normalize(); 2267 LOG( 4, "DEBUG: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << ".");2179 LOG(3, "DEBUG: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "."); 2268 2180 2269 2181 // test whether old center is on the band's plane … … 2274 2186 radius = RelativeOldSphereCenter.NormSquared(); 2275 2187 if (fabs(radius - CircleRadius) < HULLEPSILON) { 2276 LOG( 4, "DEBUG: RelativeOldSphereCenter is at " << RelativeOldSphereCenter << ".");2188 LOG(3, "DEBUG: RelativeOldSphereCenter is at " << RelativeOldSphereCenter << "."); 2277 2189 2278 2190 // check SearchDirection 2279 LOG( 4, "DEBUG: SearchDirection is " << SearchDirection << ".");2191 LOG(3, "DEBUG: SearchDirection is " << SearchDirection << "."); 2280 2192 if (fabs(RelativeOldSphereCenter.ScalarProduct(SearchDirection)) > HULLEPSILON) { // rotated the wrong way! 2281 2193 ELOG(1, "SearchDirection and RelativeOldSphereCenter are not orthogonal!"); … … 2318 2230 // find center on the plane 2319 2231 GetCenterofCircumcircle(NewPlaneCenter, CandidateLine.BaseLine->endpoints[0]->node->getPosition(), CandidateLine.BaseLine->endpoints[1]->node->getPosition(), Candidate->getPosition()); 2320 LOG( 5, "DEBUG: NewPlaneCenter is " << NewPlaneCenter << ".");2232 LOG(3, "DEBUG: NewPlaneCenter is " << NewPlaneCenter << "."); 2321 2233 2322 2234 try { 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 << "."); 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 << "."); 2325 2239 radius = CandidateLine.BaseLine->endpoints[0]->node->DistanceSquared(NewPlaneCenter); 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 << ".");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 << "."); 2329 2243 if (radius < RADIUS * RADIUS) { 2330 2244 otherradius = CandidateLine.BaseLine->endpoints[1]->node->DistanceSquared(NewPlaneCenter); … … 2332 2246 // construct both new centers 2333 2247 NewSphereCenter = NewPlaneCenter; 2334 OtherNewSphereCenter 2248 OtherNewSphereCenter= NewPlaneCenter; 2335 2249 helper = NewNormalVector; 2336 2250 helper.Scale(sqrt(RADIUS * RADIUS - radius)); 2337 LOG( 5, "DEBUG: Distance of NewPlaneCenter " << NewPlaneCenter << " to either NewSphereCenter is " << helper.Norm() << " of vector " << helper << " with sphere radius " << RADIUS << ".");2251 LOG(4, "DEBUG: Distance of NewPlaneCenter " << NewPlaneCenter << " to either NewSphereCenter is " << helper.Norm() << " of vector " << helper << " with sphere radius " << RADIUS << "."); 2338 2252 NewSphereCenter += helper; 2339 LOG( 5, "DEBUG: NewSphereCenter is at " << NewSphereCenter << ".");2253 LOG(4, "DEBUG: NewSphereCenter is at " << NewSphereCenter << "."); 2340 2254 // OtherNewSphereCenter is created by the same vector just in the other direction 2341 2255 helper.Scale(-1.); 2342 2256 OtherNewSphereCenter += helper; 2343 LOG( 5, "DEBUG: OtherNewSphereCenter is at " << OtherNewSphereCenter << ".");2257 LOG(4, "DEBUG: OtherNewSphereCenter is at " << OtherNewSphereCenter << "."); 2344 2258 alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection, HULLEPSILON); 2345 2259 Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection, HULLEPSILON); … … 2362 2276 if ((CandidateLine.ShortestAngle - HULLEPSILON) < alpha) { 2363 2277 CandidateLine.pointlist.push_back(Candidate); 2364 LOG( 3, "ACCEPT: We have found an equally good candidate: " << *(Candidate) << " with " << alpha << " and circumsphere's center at " << CandidateLine.OptCenter << ".");2278 LOG(2, "ACCEPT: We have found an equally good candidate: " << *(Candidate) << " with " << alpha << " and circumsphere's center at " << CandidateLine.OptCenter << "."); 2365 2279 } else { 2366 2280 // remove all candidates from the list and then the list itself 2367 2281 CandidateLine.pointlist.clear(); 2368 2282 CandidateLine.pointlist.push_back(Candidate); 2369 LOG( 3, "ACCEPT: We have found a better candidate: " << *(Candidate) << " with " << alpha << " and circumsphere's center at " << CandidateLine.OptCenter << ".");2283 LOG(2, "ACCEPT: We have found a better candidate: " << *(Candidate) << " with " << alpha << " and circumsphere's center at " << CandidateLine.OptCenter << "."); 2370 2284 } 2371 2285 CandidateLine.ShortestAngle = alpha; 2372 LOG( 4, "DEBUG: There are " << CandidateLine.pointlist.size() << " candidates in the list now.");2286 LOG(2, "DEBUG: There are " << CandidateLine.pointlist.size() << " candidates in the list now."); 2373 2287 } else { 2374 2288 if ((Candidate != NULL) && (CandidateLine.pointlist.begin() != CandidateLine.pointlist.end())) { 2375 LOG( 4, "REJECT: Old candidate " << *(*CandidateLine.pointlist.begin()) << " with " << CandidateLine.ShortestAngle << " is better than new one " << *Candidate << " with " << alpha << " .");2289 LOG(3, "REJECT: Old candidate " << *(*CandidateLine.pointlist.begin()) << " with " << CandidateLine.ShortestAngle << " is better than new one " << *Candidate << " with " << alpha << " ."); 2376 2290 } else { 2377 LOG( 4, "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected.");2291 LOG(3, "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected."); 2378 2292 } 2379 2293 } 2380 2294 } else { 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)));2295 ELOG(0, "REJECT: Distance to center of circumcircle is not the same from each corner of the triangle: " << fabs(radius - otherradius)); 2382 2296 } 2383 2297 } else { 2384 LOG( 4, "REJECT: NewSphereCenter " << NewSphereCenter << " for " << *Candidate << " is too far away: " << radius << ".");2298 LOG(3, "REJECT: NewSphereCenter " << NewSphereCenter << " for " << *Candidate << " is too far away: " << radius << "."); 2385 2299 } 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."); 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."); 2389 2304 } 2390 2305 } else { 2391 2306 if (ThirdPoint != NULL) { 2392 LOG( 4, "REJECT: Base triangle " << *CandidateLine.BaseLine << " and " << *ThirdPoint << " contains Candidate " << *Candidate << ".");2307 LOG(3, "REJECT: Base triangle " << *CandidateLine.BaseLine << " and " << *ThirdPoint << " contains Candidate " << *Candidate << "."); 2393 2308 } else { 2394 LOG( 4, "REJECT: Base triangle " << *CandidateLine.BaseLine << " contains Candidate " << *Candidate << ".");2309 LOG(3, "REJECT: Base triangle " << *CandidateLine.BaseLine << " contains Candidate " << *Candidate << "."); 2395 2310 } 2396 2311 } … … 2403 2318 } else { 2404 2319 if (ThirdPoint != NULL) 2405 LOG( 4, "DEBUG:Circumcircle for base line " << *CandidateLine.BaseLine << " and third node " << *ThirdPoint << " is too big!");2320 LOG(3, "Circumcircle for base line " << *CandidateLine.BaseLine << " and third node " << *ThirdPoint << " is too big!"); 2406 2321 else 2407 LOG( 4, "DEBUG:Circumcircle for base line " << *CandidateLine.BaseLine << " is too big!");2408 } 2409 2410 LOG( 5, "DEBUG: Sorting candidate list ...");2322 LOG(3, "Circumcircle for base line " << *CandidateLine.BaseLine << " is too big!"); 2323 } 2324 2325 LOG(2, "DEBUG: Sorting candidate list ..."); 2411 2326 if (CandidateLine.pointlist.size() > 1) { 2412 2327 CandidateLine.pointlist.unique(); … … 2414 2329 } 2415 2330 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!")); 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 } 2417 2335 } 2418 2336 ; … … 2426 2344 { 2427 2345 //Info FunctionInfo(__func__); 2428 const BoundaryLineSet * lines[2] = { line1, line2};2346 const BoundaryLineSet * lines[2] = { line1, line2 }; 2429 2347 class BoundaryPointSet *node = NULL; 2430 2348 PointMap OrderMap; … … 2433 2351 // for both lines 2434 2352 for (int j = 0; j < 2; j++) { // for both endpoints 2435 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));2353 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j])); 2436 2354 if (!OrderTest.second) { // if insertion fails, we have common endpoint 2437 2355 node = OrderTest.first->second; … … 2482 2400 // we should make sure that both triangles end up in the same entry 2483 2401 // in the distance multimap. Hence, we round to 6 digit precision. 2484 const double distance = 1e-6 * floor(FindPoint->second->node->DistanceSquared(x) * 1e+6); 2402 const double distance = 2403 1e-6*floor(FindPoint->second->node->DistanceSquared(x)*1e+6); 2485 2404 points->insert(DistanceToPointPair(distance, FindPoint->second)); 2486 2405 LOG(3, "DEBUG: Putting " << *FindPoint->second << " into the list."); … … 2527 2446 for (LineMap::iterator LineRunner = Runner->second->lines.begin(); LineRunner != Runner->second->lines.end(); LineRunner++) { 2528 2447 // calculate closest point on line to desired point 2529 helper = 0.5 * (((LineRunner->second)->endpoints[0]->node->getPosition()) + ((LineRunner->second)->endpoints[1]->node->getPosition())); 2448 helper = 0.5 * (((LineRunner->second)->endpoints[0]->node->getPosition()) + 2449 ((LineRunner->second)->endpoints[1]->node->getPosition())); 2530 2450 Center = (x) - helper; 2531 BaseLine = ((LineRunner->second)->endpoints[0]->node->getPosition()) - ((LineRunner->second)->endpoints[1]->node->getPosition()); 2451 BaseLine = ((LineRunner->second)->endpoints[0]->node->getPosition()) - 2452 ((LineRunner->second)->endpoints[1]->node->getPosition()); 2532 2453 Center.ProjectOntoPlane(BaseLine); 2533 2454 const double distance = Center.NormSquared(); … … 2586 2507 for (LineMap::iterator LineRunner = Runner->second->lines.begin(); LineRunner != Runner->second->lines.end(); LineRunner++) { 2587 2508 2588 BaseLine = ((LineRunner->second)->endpoints[0]->node->getPosition()) - ((LineRunner->second)->endpoints[1]->node->getPosition()); 2509 BaseLine = ((LineRunner->second)->endpoints[0]->node->getPosition()) - 2510 ((LineRunner->second)->endpoints[1]->node->getPosition()); 2589 2511 const double lengthBase = BaseLine.NormSquared(); 2590 2512 … … 2602 2524 MinDistance = lengthEnd; 2603 2525 LOG(1, "ACCEPT: Line " << *LineRunner->second << " to endpoint " << *LineRunner->second->endpoints[0]->node << " is closer with " << lengthEnd << "."); 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 } 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 } 2611 2532 } else { // intersection is closer, calculate 2612 2533 // calculate closest point on line to desired point … … 2734 2655 double distance = 0.; 2735 2656 2736 if (triangle == NULL) { 2657 if (triangle == NULL) {// is boundary point or only point in point cloud? 2737 2658 LOG(1, "No triangle given!"); 2738 2659 return -1.; … … 2843 2764 takePoint = true; 2844 2765 current = findLines->second->endpoints[1]->node; 2845 } else 2846 if (findLines->second->endpoints[1]->Nr == Point->getNr()) { 2847 takePoint = true; 2848 current = findLines->second->endpoints[0]->node; 2849 } 2766 } else if (findLines->second->endpoints[1]->Nr == Point->getNr()) { 2767 takePoint = true; 2768 current = findLines->second->endpoints[0]->node; 2769 } 2850 2770 2851 2771 if (takePoint) { … … 2887 2807 Vector OrthogonalVector; 2888 2808 Vector helper; 2889 const TesselPoint * const TrianglePoints[3] = { Point, NULL, NULL};2809 const TesselPoint * const TrianglePoints[3] = { Point, NULL, NULL }; 2890 2810 TriangleList *triangles = NULL; 2891 2811 … … 2898 2818 // calculate central point 2899 2819 triangles = FindTriangles(TrianglePoints); 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; 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 } 2903 2827 PlaneNormal.Scale(1.0 / triangles->size()); 2904 2828 LOG(4, "DEBUG: Calculated PlaneNormal of all circle points is " << PlaneNormal << "."); … … 2912 2836 AngleZero = ((*SetOfNeighbours->begin())->getPosition()) - (Point->getPosition()); 2913 2837 AngleZero.ProjectOntoPlane(PlaneNormal); 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!")); 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 } 2915 2842 } 2916 2843 LOG(4, "DEBUG: Reference vector on this plane representing angle 0 is " << AngleZero << "."); 2917 2844 if (AngleZero.NormSquared() > MYEPSILON) 2918 OrthogonalVector = Plane(PlaneNormal, AngleZero, 2845 OrthogonalVector = Plane(PlaneNormal, AngleZero,0).getNormal(); 2919 2846 else 2920 2847 OrthogonalVector.MakeNormalTo(PlaneNormal); … … 2927 2854 double angle = GetAngle(helper, AngleZero, OrthogonalVector); 2928 2855 LOG(4, "DEBUG" << angle << " for point " << **listRunner << "."); 2929 anglesOfPoints.insert(pair<double, TesselPoint*> (angle, (*listRunner)));2856 anglesOfPoints.insert(pair<double, TesselPoint*> (angle, (*listRunner))); 2930 2857 } 2931 2858 … … 2982 2909 int counter = 0; 2983 2910 while (TesselC != SetOfNeighbours->end()) { 2984 helper = Plane(((*TesselA)->getPosition()), ((*TesselB)->getPosition()), ((*TesselC)->getPosition())).getNormal(); 2911 helper = Plane(((*TesselA)->getPosition()), 2912 ((*TesselB)->getPosition()), 2913 ((*TesselC)->getPosition())).getNormal(); 2985 2914 LOG(5, "DEBUG: Making normal vector out of " << *(*TesselA) << ", " << *(*TesselB) << " and " << *(*TesselC) << ":" << helper); 2986 2915 counter++; … … 2991 2920 } 2992 2921 //LOG(0, "Summed vectors " << center << "; number of points " << connectedPoints.size() << "; scale factor " << counter); 2993 PlaneNormal.Scale(1.0 / (double) counter);2922 PlaneNormal.Scale(1.0 / (double) counter); 2994 2923 // LOG(1, "INFO: Calculated center of all circle points is " << center << "."); 2995 2924 // … … 3005 2934 AngleZero.ProjectOntoPlane(PlaneNormal); 3006 2935 } 3007 if ((Reference.IsZero()) || (AngleZero.NormSquared() < MYEPSILON )) {2936 if ((Reference.IsZero()) || (AngleZero.NormSquared() < MYEPSILON )) { 3008 2937 LOG(4, "DEBUG: Using alternatively " << (*SetOfNeighbours->begin())->getPosition() << " as angle 0 referencer."); 3009 2938 AngleZero = ((*SetOfNeighbours->begin())->getPosition()) - (Point->getPosition()); 3010 2939 AngleZero.ProjectOntoPlane(PlaneNormal); 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!")); 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 } 3012 2944 } 3013 2945 LOG(4, "DEBUG: Reference vector on this plane representing angle 0 is " << AngleZero << "."); 3014 2946 if (AngleZero.NormSquared() > MYEPSILON) 3015 OrthogonalVector = Plane(PlaneNormal, AngleZero, 2947 OrthogonalVector = Plane(PlaneNormal, AngleZero,0).getNormal(); 3016 2948 else 3017 2949 OrthogonalVector.MakeNormalTo(PlaneNormal); … … 3027 2959 angle = 2. * M_PI - angle; 3028 2960 LOG(4, "DEBUG: Calculated angle between " << helper << " and " << AngleZero << " is " << angle << " for point " << **listRunner << "."); 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)))); 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 } 3031 2966 } 3032 2967 … … 3048 2983 //Info FunctionInfo(__func__); 3049 2984 map<double, TesselPoint*> anglesOfPoints; 3050 list<TesselPointList *> *ListOfPaths = new list<TesselPointList *> ;2985 list<TesselPointList *> *ListOfPaths = new list<TesselPointList *> ; 3051 2986 TesselPointList *connectedPath = NULL; 3052 2987 Vector center; … … 3074 3009 map<class BoundaryTriangleSet *, bool>::iterator TriangleRunner; 3075 3010 for (LineMap::iterator Runner = ReferencePoint->lines.begin(); Runner != ReferencePoint->lines.end(); Runner++) { 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 } 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)); 3082 3014 } 3083 3015 if (!ReferencePoint->lines.empty()) { … … 3086 3018 if (LineRunner == TouchedLine.end()) { 3087 3019 ELOG(1, "I could not find " << *runner->second << " in the touched list."); 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 } 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; 3117 3044 } else { 3118 ELOG(1, "I could not find " << *triangle << " in the touched list.");3045 LOG(1, "INFO: Skipping " << *triangle << ", as we have already visited it."); 3119 3046 triangle = NULL; 3120 3047 } 3121 3048 } else { 3122 // as we have stumbled upon the same triangle, we don't need the check anymore3049 ELOG(1, "I could not find " << *triangle << " in the touched list."); 3123 3050 triangle = NULL; 3124 3051 } 3125 3052 } 3126 if (triangle == NULL) 3053 } 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 << "."); 3127 3061 break; 3128 // find next line3129 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 Point3131 CurrentLine = triangle->lines[i];3132 LOG(3, "INFO: Connecting line is " << *CurrentLine << ".");3133 break;3134 }3135 3062 } 3136 LineRunner = TouchedLine.find(CurrentLine);3137 if (LineRunner == TouchedLine.end())3138 ELOG(1, "I could not find " << *CurrentLine << " in the touched list.");3139 else3140 LineRunner->second = true;3141 // find next point3142 CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint);3143 3144 } while (CurrentLine != StartLine);3145 // last point is missing, as it's on start line3146 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);3149 3063 } 3150 3151 ListOfPaths->push_back(connectedPath); 3152 } else { 3153 LOG(3, "DEBUG: Skipping " << *runner->second << ", as we have already visited it."); 3154 } 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 } 3155 3082 } 3156 3083 } else { … … 3171 3098 //Info FunctionInfo(__func__); 3172 3099 list<TesselPointList *> *ListofPaths = GetPathsOfConnectedPoints(Point); 3173 list<TesselPointList *> *ListofClosedPaths = new list<TesselPointList *> ;3100 list<TesselPointList *> *ListofClosedPaths = new list<TesselPointList *> ; 3174 3101 TesselPointList *connectedPath = NULL; 3175 3102 TesselPointList *newPath = NULL; … … 3181 3108 connectedPath = *ListRunner; 3182 3109 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 } 3110 LOG(1, "INFO: Current path is " << connectedPath << "."); 3191 3111 3192 3112 // go through list, look for reappearance of starting Point and count … … 3197 3117 if ((*CircleRunner == *CircleStart) && (CircleRunner != CircleStart)) { // is not the very first point 3198 3118 // we have a closed circle from Marker to new Marker 3199 if (DoLog( 3)) {3119 if (DoLog(1)) { 3200 3120 std::stringstream output; 3201 output << "DEBUG: " << count + 1 << ". closed path consists of: "; 3202 for (TesselPointList::iterator CircleSprinter = Marker; CircleSprinter != CircleRunner; CircleSprinter++) 3121 output << count + 1 << ". closed path consists of: "; 3122 for (TesselPointList::iterator CircleSprinter = Marker; 3123 CircleSprinter != CircleRunner; 3124 CircleSprinter++) 3203 3125 output << (**CircleSprinter) << " <-> "; 3204 3126 LOG(1, output.str()); … … 3216 3138 } 3217 3139 } 3218 LOG( 2, "DEBUG: " << count << " closed additional path(s) have been created.");3140 LOG(1, "INFO: " << count << " closed additional path(s) have been created."); 3219 3141 3220 3142 // delete list of paths … … 3254 3176 } 3255 3177 ; 3256 3257 struct CloserToPiHalf3258 {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) const3266 {3267 // check for NULL3268 if (_point == NULL) {3269 return false;3270 }3271 3272 // get list of connected points3273 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 point3290 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 direction3298 TesselPointList::const_iterator ListRunner = ListAdvance++;3299 for (; (ListAdvance != connectedPath->end()) && PointIsBelow;3300 ListRunner = ListAdvance++) { // go through all closed paths3301 LOG(2, "DEBUG: Current reference node is " << **ListRunner3302 << ", advanced node is " << **ListAdvance);3303 3304 // reference vector to point to check for this point of connected path3305 const Vector Reference =3306 ((*ListAdvance)->getPosition()) - ((*ListRunner)->getPosition());3307 3308 // go through all other points in this connected path3309 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 vector3319 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 triangles3324 if (NormalVector.ScalarProduct(OrthogonalVector) < 0)3325 NormalVector *= -1.;3326 try {3327 Plane plane(NormalVector, ((*ListRunner)->getPosition()));3328 3329 // check whether point is below3330 if (plane.SignedDistance(_point->node->getPosition()) > 0) {3331 LOG(2, "DEBUG: For plane " << plane << " point " << *_point3332 << " 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 connectedPath3355 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 list3385 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 neighbours3391 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 neighbour3395 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 polygon3416 if (*maxiter > M_PI) {3417 // connectedPath is not convex: The idea is to fill any kinks pointing3418 // inside into the connectedPath close to this concave spot first, making3419 // it eventually become convex.3420 // Hence, use adjacent (and convex) fill-in point3421 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 convex3430 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 tetraeder3484 volume += CalculateVolumeofGeneralTetraeder(3485 TPS[0]->node->getPosition(),3486 TPS[1]->node->getPosition(),3487 TPS[2]->node->getPosition(),3488 OldPoint);3489 // advance number3490 ++count;3491 3492 // prepare nodes for next triangle3493 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 done3499 connectedPath->remove(*StartNode); // remove the start node3500 connectedPath->remove(*EndNode); // remove the end node3501 }3502 }3503 LOG(1, "INFO: " << count << " triangles were created.");3504 3505 return volume;3506 }3507 3178 3508 3179 /** Removes a boundary point from the envelope while keeping it closed. … … 3519 3190 double Tesselation::RemovePointFromTesselatedSurface(class BoundaryPointSet *point) 3520 3191 { 3192 class BoundaryLineSet *line = NULL; 3193 class BoundaryTriangleSet *triangle = NULL; 3194 Vector OldPoint, NormalVector; 3521 3195 double volume = 0; 3196 int count = 0; 3522 3197 3523 3198 if (point == NULL) { … … 3527 3202 LOG(4, "DEBUG: Removing point " << *point << " from tesselated boundary ..."); 3528 3203 3204 // copy old location for the volume 3205 OldPoint = (point->node->getPosition()); 3206 3529 3207 // get list of connected points 3530 3208 if (point->lines.empty()) { … … 3534 3212 3535 3213 list<TesselPointList *> *ListOfClosedPaths = GetClosedPathsOfConnectedPoints(point->node); 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); 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 3660 3239 list<TesselPointList *>::iterator ListAdvance = ListOfClosedPaths->begin(); 3661 3240 list<TesselPointList *>::iterator ListRunner = ListAdvance; 3662 3241 // TriangleMap::iterator NumberRunner = Candidates.begin(); 3663 3242 TesselPointList::iterator StartNode, MiddleNode, EndNode; 3243 double angle; 3244 double smallestangle; 3664 3245 Vector Point, Reference, OrthogonalVector; 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); 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."); 3678 3392 } 3679 3393 delete (ListOfClosedPaths); 3680 3394 3681 if (volume > 0.) 3682 LOG(1, "INFO: Removed volume is " << volume << "."); 3395 LOG(1, "INFO: Removed volume is " << volume << "."); 3683 3396 3684 3397 return volume; … … 3724 3437 if (TrianglePoints[j] != NULL) { 3725 3438 for (FindLine = TrianglePoints[i]->lines.find(TrianglePoints[j]->node->getNr()); // is a multimap! 3726 3439 (FindLine != TrianglePoints[i]->lines.end()) && (FindLine->first == TrianglePoints[j]->node->getNr()); FindLine++) { 3727 3440 for (FindTriangle = FindLine->second->triangles.begin(); FindTriangle != FindLine->second->triangles.end(); FindTriangle++) { 3728 3441 if (FindTriangle->second->IsPresentTupel(TrianglePoints)) { … … 3745 3458 break; 3746 3459 for (FindLine = TrianglePoints[(i + 1) % 3]->lines.find(TrianglePoints[(i + 2) % 3]->node->getNr()); // is a multimap! 3747 3460 (FindLine != TrianglePoints[(i + 1) % 3]->lines.end()) && (FindLine->first == TrianglePoints[(i + 2) % 3]->node->getNr()); FindLine++) { 3748 3461 for (FindTriangle = FindLine->second->triangles.begin(); FindTriangle != FindLine->second->triangles.end(); FindTriangle++) { 3749 3462 if (FindTriangle->second->IsPresentTupel(TrianglePoints)) { … … 3774 3487 } 3775 3488 default: 3776 ASSERT(0, "Tesselation::FindTriangles() - Number of wildcards is greater than 3, cannot happen!"); 3489 ELOG(0, "Number of wildcards is greater than 3, cannot happen!"); 3490 performCriticalExit(); 3777 3491 break; 3778 3492 } … … 3800 3514 if (a->endpoints[lowerNra] < b->endpoints[lowerNrb]) 3801 3515 return true; 3802 else 3803 if (a->endpoints[lowerNra] > b->endpoints[lowerNrb]) 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]) 3804 3522 return false; 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 } 3523 } 3812 3524 return false; 3813 3525 } … … 3830 3542 3831 3543 // sanity check 3832 3833 3834 3835 3836 3837 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; 3838 3550 for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) { 3839 3551 tester = AllLines.insert(LineRunner1->second); … … 3852 3564 const LineMap::const_iterator Line2 = LinesOnBoundary.find((*it).second); 3853 3565 if (Line1 != LinesOnBoundary.end() && Line2 != LinesOnBoundary.end()) 3854 LOG(3, "DEBUG: " << *Line1->second << " => " << *Line2->second);3566 LOG(3, "DEBUG: " << *Line1->second << " => " << *Line2->second); 3855 3567 else 3856 ELOG(1, "Either " << (*it).first << " or " << (*it).second << " are not in LinesOnBoundary!");3568 ELOG(1, "Either " << (*it).first << " or " << (*it).second << " are not in LinesOnBoundary!"); 3857 3569 } 3858 3570 … … 3886 3598 for (TriangleRunner2 = line2->triangles.begin(); TriangleRunner2 != line2->triangles.end(); ++TriangleRunner2) { 3887 3599 if ((TriangleRunner1->second != TriangleRunner2->second) && (TriangleRunner1->second->IsPresentTupel(TriangleRunner2->second))) { 3888 DegeneratedTriangles->insert(pair<int, int> (TriangleRunner1->second->Nr, TriangleRunner2->second->Nr));3889 DegeneratedTriangles->insert(pair<int, int> (TriangleRunner2->second->Nr, TriangleRunner1->second->Nr));3600 DegeneratedTriangles->insert(pair<int, int> (TriangleRunner1->second->Nr, TriangleRunner2->second->Nr)); 3601 DegeneratedTriangles->insert(pair<int, int> (TriangleRunner2->second->Nr, TriangleRunner1->second->Nr)); 3890 3602 } 3891 3603 } … … 3914 3626 3915 3627 // iterate over all degenerated triangles 3916 for (IndexToIndex::iterator TriangleKeyRunner = DegeneratedTriangles->begin(); 3917 !DegeneratedTriangles->empty(); 3918 TriangleKeyRunner = DegeneratedTriangles->begin()) { 3628 for (IndexToIndex::iterator TriangleKeyRunner = DegeneratedTriangles->begin(); !DegeneratedTriangles->empty(); TriangleKeyRunner = DegeneratedTriangles->begin()) { 3919 3629 LOG(3, "DEBUG: Checking presence of triangles " << TriangleKeyRunner->first << " and " << TriangleKeyRunner->second << "."); 3920 3630 // both ways are stored in the map, only use one … … 3957 3667 // OtherpartnerTriangle = TriangleRunner->second; 3958 3668 // } 3959 3960 3961 3669 /// interchanges their lines so that triangle->lines[i] == partnerTriangle->lines[j] 3670 // the line of triangle receives the degenerated ones 3671 triangle->lines[i]->triangles.erase(Othertriangle->Nr); 3962 3672 triangle->lines[i]->triangles.insert(TrianglePair(partnerTriangle->Nr, partnerTriangle)); 3963 3673 for (int k = 0; k < 3; k++) … … 3973 3683 3974 3684 // erase the pair 3975 count += (int) DegeneratedTriangles->erase(triangle->Nr);3685 count += (int) DegeneratedTriangles->erase(triangle->Nr); 3976 3686 LOG(4, "DEBUG: RemoveDegeneratedTriangles() removes triangle " << *triangle << "."); 3977 3687 RemoveTesselationTriangle(triangle); 3978 count += (int) DegeneratedTriangles->erase(partnerTriangle->Nr);3688 count += (int) DegeneratedTriangles->erase(partnerTriangle->Nr); 3979 3689 LOG(4, "DEBUG: RemoveDegeneratedTriangles() removes triangle " << *partnerTriangle << "."); 3980 3690 RemoveTesselationTriangle(partnerTriangle); 3981 3691 } else { 3982 3692 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 nonetheless3984 DegeneratedTriangles->erase(triangle->Nr);3985 DegeneratedTriangles->erase(partnerTriangle->Nr);3986 3693 } 3987 3694 } … … 4027 3734 class BoundaryLineSet *BestLine = NULL; 4028 3735 for (LineMap::iterator Runner = NearestBoundaryPoint->lines.begin(); Runner != NearestBoundaryPoint->lines.end(); Runner++) { 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())); 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())); 4031 3740 CenterToPoint -= (point->getPosition()); 4032 3741 angle = CenterToPoint.Angle(BaseLine); 4033 if (fabs(angle - M_PI / 2.) < fabs(BestAngle - M_PI /2.)) {3742 if (fabs(angle - M_PI/2.) < fabs(BestAngle - M_PI/2.)) { 4034 3743 BestAngle = angle; 4035 3744 BestLine = Runner->second; … … 4080 3789 for (int i = 0; i < 3; i++) { // look for the same line as BestLine (only it's its degenerated companion) 4081 3790 if ((BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[0])) && (BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[1]))) { 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)); 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)); 4084 3796 TempTriangle->lines[nr] = BTS->lines[i]; 4085 3797 break; … … 4103 3815 if (LastTriangle != NULL) { 4104 3816 stringstream sstr; 4105 sstr << "-" 3817 sstr << "-"<< TrianglesOnBoundary.size() << "-" << LastTriangle->getEndpointName(0) << "_" << LastTriangle->getEndpointName(1) << "_" << LastTriangle->getEndpointName(2); 4106 3818 NumberName = sstr.str(); 4107 3819 if (DoTecplotOutput) { … … 4145 3857 if (s1->endpoints.size() < s2->endpoints.size()) 4146 3858 return true; 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; 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++; 4163 3871 } 3872 return false; 3873 } 4164 3874 } 4165 3875 }; … … 4186 3896 for (TriangleMap::const_iterator TriangleRunner = (LineRunner->second)->triangles.begin(); TriangleRunner != (LineRunner->second)->triangles.end(); TriangleRunner++) { 4187 3897 if (DegeneratedTriangles->find(TriangleRunner->second->Nr) == DegeneratedTriangles->end()) { 4188 TriangleInsertionTester = TriangleVectors.insert(pair<int, Vector *> ((TriangleRunner->second)->Nr, &((TriangleRunner->second)->NormalVector)));3898 TriangleInsertionTester = TriangleVectors.insert(pair<int, Vector *> ((TriangleRunner->second)->Nr, &((TriangleRunner->second)->NormalVector))); 4189 3899 if (TriangleInsertionTester.second) 4190 3900 LOG(5, "DEBUG: Adding triangle " << *(TriangleRunner->second) << " to triangles to check-list."); … … 4199 3909 if (VectorWalker != VectorRunner) { // skip equals 4200 3910 const double SCP = VectorWalker->second->ScalarProduct(*VectorRunner->second); // ScalarProduct should result in -1. for degenerated triangles 4201 LOG(4, "DEBUG: Checking " << * (VectorWalker->second) << " against " << *(VectorRunner->second)<< ": " << SCP);3911 LOG(4, "DEBUG: Checking " << *VectorWalker->second << " against " << *VectorRunner->second << ": " << SCP); 4202 3912 if (fabs(SCP + 1.) < ParallelEpsilon) { 4203 3913 InsertionTester = EndpointCandidateList.insert((Runner->second)); … … 4281 3991 // The Problem is probably due to two degenerated polygons being connected by a bridging, non-degenerated polygon, as somehow one node has 4282 3992 // connections to either polygon ... 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!")); 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 } 4284 3997 TriangleSet::iterator TriangleWalker = T->begin(); // is the inner iterator 4285 3998 /// 4a. Get NormalVector for one side (this is "front")
Note:
See TracChangeset
for help on using the changeset viewer.