PolyhedronTest.cc 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //
  2. // Copyright (C) 2014 OpenSim Ltd.
  3. //
  4. // This program is free software; you can redistribute it and/or
  5. // modify it under the terms of the GNU Lesser General Public License
  6. // as published by the Free Software Foundation; either version 2
  7. // of the License, or (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with this program; if not, see <http://www.gnu.org/licenses/>.
  16. //
  17. #include "PolyhedronTest.h"
  18. #include "inet/common/geometry/shape/polyhedron/PolyhedronPoint.h"
  19. #include "inet/common/geometry/shape/polyhedron/PolyhedronFace.h"
  20. namespace inet {
  21. Define_Module(PolyhedronTest);
  22. PolyhedronTest::PolyhedronTest()
  23. {
  24. polyhedron = NULL;
  25. }
  26. void PolyhedronTest::parsePoints(const char* strPoints)
  27. {
  28. cStringTokenizer tokenizer(strPoints);
  29. double x, y, z;
  30. while (tokenizer.hasMoreTokens())
  31. {
  32. x = atof(tokenizer.nextToken());
  33. if (tokenizer.hasMoreTokens())
  34. y = atof(tokenizer.nextToken());
  35. if (tokenizer.hasMoreTokens())
  36. {
  37. z = atof(tokenizer.nextToken());
  38. Coord point(x,y,z);
  39. points.push_back(point);
  40. }
  41. }
  42. }
  43. void PolyhedronTest::printFaces() const
  44. {
  45. const Polyhedron::Faces& faces = polyhedron->getFaces();
  46. for (Polyhedron::Faces::const_iterator fit = faces.begin(); fit != faces.end(); fit++)
  47. {
  48. std::cout << "Face with edges: " << endl;
  49. Polyhedron::Edges edges = (*fit)->getEdges();
  50. for (Polyhedron::Edges::iterator eit = edges.begin(); eit != edges.end(); eit++)
  51. {
  52. PolyhedronEdge *edge = *eit;
  53. std::cout << "P1 = " << *edge->getP1() << " P2 = " << *edge->getP2() << endl;
  54. }
  55. }
  56. }
  57. void PolyhedronTest::initialize(int stage)
  58. {
  59. if (stage == INITSTAGE_LOCAL)
  60. {
  61. const char *strPoints = par("points").stringValue();
  62. bool testWithConvexCombations = par("convexCombinationTest").boolValue();
  63. parsePoints(strPoints);
  64. polyhedron = new Polyhedron(points);
  65. printFaces();
  66. if (testWithConvexCombations)
  67. test();
  68. }
  69. }
  70. void PolyhedronTest::test() const
  71. {
  72. // Let P := {p_1,p_2,...,p_n} be a point set with finite number of elements then conv(P)
  73. // (donates the convex hull of P) is the minimal convex set containing P, and equivalently
  74. // is the set of all convex combinations of points in P.
  75. // So we can test our algorithm in the following way:
  76. // Generate a lot of convex combinations and test if the combination is in the convex hull.
  77. // If it is not, then the algorithm is incorrect.
  78. unsigned int numberOfPoints = points.size();
  79. // We are testing with 1000 random convex combination.
  80. const Polyhedron::Faces& faces = polyhedron->getFaces();
  81. for (unsigned int i = 1; i != 1000; i++)
  82. {
  83. // Create a convex combination:
  84. // lambda_1 p_1 + lambda_2 p_2 + ... + lambda_n p_n where lambda_1 +
  85. // lambda_2 + ... + lambda_n = 1 and lambda_k >= 0 for all k.
  86. double lambda = 1.0;
  87. unsigned int id = 0;
  88. Coord convexCombination;
  89. while (id < numberOfPoints - 1)
  90. {
  91. double randLambda = (rand() % 5000) / 10000.0;
  92. while (lambda - randLambda < 0)
  93. randLambda = (rand() % 5000) / 10000.0;
  94. lambda -= randLambda;
  95. convexCombination += points[id++] * randLambda;
  96. }
  97. convexCombination += points[numberOfPoints - 1] * lambda;
  98. std::cout << "Testing with convex combination: " << convexCombination << endl;
  99. for (Polyhedron::Faces::const_iterator fit = faces.begin(); fit != faces.end(); fit++)
  100. {
  101. PolyhedronFace *face = *fit;
  102. PolyhedronPoint testPoint(convexCombination);
  103. // An arbitrary point is an inner point if and only if it can't see any faces.
  104. // KLUDGE: this check supposed to be face->isVisibleFrom(&testPoint) but it's too sensible due to >0
  105. PolyhedronPoint *facePoint = face->getEdge(0)->getP1();
  106. PolyhedronPoint facePointPoint = testPoint - *facePoint;
  107. if (facePointPoint * face->getOutwardNormalVector() > 1E-10) {
  108. std::cout << "The algorithm is incorrect!" << endl;
  109. return;
  110. }
  111. }
  112. }
  113. }
  114. PolyhedronTest::~PolyhedronTest()
  115. {
  116. delete polyhedron;
  117. }
  118. } /* namespace inet */