INET Framework for OMNeT++/OMNEST
inet::Polyhedron Class Reference

#include <Polyhedron.h>

Inheritance diagram for inet::Polyhedron:
inet::ShapeBase

Public Types

typedef std::vector< PolyhedronPoint * > Points
 
typedef std::vector< PolyhedronFace * > Faces
 
typedef std::vector< PolyhedronEdge * > Edges
 

Public Member Functions

 Polyhedron (const std::vector< Coord > &points)
 
Coord computeBoundingBoxSize () const override
 Computes the 3 dimensional size of the shapes's bounding box. More...
 
void computeVisibleFaces (std::vector< std::vector< Coord > > &faces, const Rotation &rotation, const Rotation &viewRotation) const
 
bool computeIntersection (const LineSegment &lineSegment, Coord &intersection1, Coord &intersection2, Coord &normal1, Coord &normal2) const override
 Computes the intersection with the given line segment in the shape's coordinate system. More...
 
const FacesgetFaces () const
 
const PointsgetPoints () const
 
virtual ~Polyhedron ()
 
- Public Member Functions inherited from inet::ShapeBase
 ShapeBase ()
 
virtual ~ShapeBase ()
 

Protected Member Functions

void purgeWrappedFaces ()
 
void buildConvexHull ()
 
bool areCollinear (const PolyhedronPoint *lineP1, const PolyhedronPoint *lineP2, const PolyhedronPoint *point) const
 
bool areCoplanar (const PolyhedronPoint *p1, const PolyhedronPoint *p2, const PolyhedronPoint *p3, const PolyhedronPoint *p4) const
 
bool areCoplanar (const PolyhedronFace *face1, const PolyhedronFace *face2) const
 
void mergeFaces (PolyhedronFace *newFace, PolyhedronFace *neighborFace, PolyhedronPoint *point)
 
void createInitialTetrahedron ()
 
void initializeConflictGraph ()
 
void cleanConflictGraph (const Faces &conflictVector)
 
void purgeConflictFaces (const Faces &conflictVector)
 
void connectFaces (PolyhedronFace *newFace)
 
void setContlictListForNewFace (PolyhedronFace *newFace, const PolyhedronFace *neighbor1, const PolyhedronFace *neighbor2)
 
void generateAndAddTetrahedronFaces (const Points &tetrahedronPoints)
 
PolyhedronPoint computeOutwardNormalVector (const PolyhedronFace *face) const
 
void addFace (PolyhedronFace *face)
 
Edges computeHorizonEdges (const Faces &visibleFaces) const
 
bool isVisibleFromView (const PolyhedronFace *face, const Rotation &viewRotation, const Rotation &rotation) const
 

Protected Attributes

Faces faces
 
Points points
 

Member Typedef Documentation

typedef std::vector<PolyhedronEdge *> inet::Polyhedron::Edges
typedef std::vector<PolyhedronFace *> inet::Polyhedron::Faces
typedef std::vector<PolyhedronPoint *> inet::Polyhedron::Points

Constructor & Destructor Documentation

inet::Polyhedron::Polyhedron ( const std::vector< Coord > &  points)
294 {
295  if (points.size() < 4)
296  throw cRuntimeError("We need at least four points");
297  for (const auto & point : points)
298  this->points.push_back(new PolyhedronPoint(point));
299  buildConvexHull();
300 }
void buildConvexHull()
Definition: Polyhedron.cc:29
Points points
Definition: Polyhedron.h:42
inet::Polyhedron::~Polyhedron ( )
virtual
465 {
466  for (auto & elem : points)
467  delete elem;
468 
469  for (auto & elem : faces)
470  delete elem;
471 
472 }
Points points
Definition: Polyhedron.h:42
Faces faces
Definition: Polyhedron.h:41

Member Function Documentation

void inet::Polyhedron::addFace ( PolyhedronFace face)
protected

Referenced by buildConvexHull(), and generateAndAddTetrahedronFaces().

166 {
167  faces.push_back(face);
168 }
Faces faces
Definition: Polyhedron.h:41
bool inet::Polyhedron::areCollinear ( const PolyhedronPoint lineP1,
const PolyhedronPoint lineP2,
const PolyhedronPoint point 
) const
protected

Referenced by createInitialTetrahedron().

84 {
85  PolyhedronPoint P1P2 = *lineP2 - *lineP1;
86  PolyhedronPoint P1Point = *point - *lineP1;
87  return P1P2 % P1Point == Coord(0,0,0);
88 }
bool inet::Polyhedron::areCoplanar ( const PolyhedronPoint p1,
const PolyhedronPoint p2,
const PolyhedronPoint p3,
const PolyhedronPoint p4 
) const
protected

Referenced by buildConvexHull(), and createInitialTetrahedron().

91 {
92  // http://mathworld.wolfram.com/Coplanar.html
93  // The volume of the tetrahedron they define.
94  return (*p3 - *p1) * ((*p2 - *p1) % (*p4 - *p3)) == 0;
95 }
bool inet::Polyhedron::areCoplanar ( const PolyhedronFace face1,
const PolyhedronFace face2 
) const
protected
211 {
212  Coord faceNormal1 = face1->getNormalVector();
213  Coord faceNormal2 = face2->getNormalVector();
214  return faceNormal1 % faceNormal2 == Coord(0,0,0);
215 }
void inet::Polyhedron::buildConvexHull ( )
protected

Referenced by Polyhedron().

30 {
32  //std::random_shuffle(points.begin(), points.end());
34  for (auto currentPoint : points)
35  {
36 
37  if (currentPoint->isSelected())
38  continue;
39  currentPoint->setToSelected();
40  // If there is no conflicts then the point is already contained in the current convex hull
41  if (currentPoint->hasConflicts())
42  {
43  // Delete all faces in currentPoint conflict vector from the hull
44  Faces& conflictVector = currentPoint->getConflictVector();
45  Faces copyConflictVector = currentPoint->getConflictVector();
46  purgeConflictFaces(conflictVector);
47  // Computes a closed curve consisting of edges of the current convex hull
48  // This closed curve can be interpreted as the border of the visible region from our current point
49  Edges horizonEdges = computeHorizonEdges(conflictVector);
50  for (auto horizonEdge : horizonEdges)
51  {
52 
53  // Faces incident to horizonEdge in the current convex hull
54  PolyhedronFace *neighborFace = horizonEdge->getJointFace();
55  PolyhedronFace *parentFace = horizonEdge->getParentFace();
56  // Connect horizonEdge to currentPoint by creating a triangular face newFace
57  PolyhedronFace *newFace = new PolyhedronFace(horizonEdge->getP1(), horizonEdge->getP2(), currentPoint);
58  // Coplanar faces have to be merged together since they define a bigger face
59  // Due to these merges the computeIntersection() algorithm will have to visit fewer faces
60  // It is clear that conflict list and outward normals are same as that of neighborFace
61  connectFaces(newFace); // TODO: optimize
62  if (areCoplanar(newFace, neighborFace))
63  {
64  mergeFaces(newFace, neighborFace, currentPoint);
65  connectFaces(neighborFace);
66  }
67  else
68  {
69  // If they are not coplanar we just add it to the faces and compute its outward normal vector
70  // and update the conflict graph
71  newFace->setOutwardNormalVector(computeOutwardNormalVector(newFace));
72  addFace(newFace);
73  setContlictListForNewFace(newFace, neighborFace, parentFace);
74  }
75  }
76  // We have to delete the old faces that wrapped by the new faces
77  cleanConflictGraph(copyConflictVector);
78  }
79  }
81 }
void setContlictListForNewFace(PolyhedronFace *newFace, const PolyhedronFace *neighbor1, const PolyhedronFace *neighbor2)
Definition: Polyhedron.cc:248
PolyhedronPoint computeOutwardNormalVector(const PolyhedronFace *face) const
Definition: Polyhedron.cc:311
std::vector< PolyhedronEdge * > Edges
Definition: Polyhedron.h:38
Points points
Definition: Polyhedron.h:42
Edges computeHorizonEdges(const Faces &visibleFaces) const
Definition: Polyhedron.cc:170
void addFace(PolyhedronFace *face)
Definition: Polyhedron.cc:165
void purgeWrappedFaces()
Definition: Polyhedron.cc:346
void mergeFaces(PolyhedronFace *newFace, PolyhedronFace *neighborFace, PolyhedronPoint *point)
Definition: Polyhedron.cc:217
void initializeConflictGraph()
Definition: Polyhedron.cc:192
void cleanConflictGraph(const Faces &conflictVector)
Definition: Polyhedron.cc:275
std::vector< PolyhedronFace * > Faces
Definition: Polyhedron.h:37
void createInitialTetrahedron()
Definition: Polyhedron.cc:97
bool areCoplanar(const PolyhedronPoint *p1, const PolyhedronPoint *p2, const PolyhedronPoint *p3, const PolyhedronPoint *p4) const
Definition: Polyhedron.cc:90
void purgeConflictFaces(const Faces &conflictVector)
Definition: Polyhedron.cc:302
void connectFaces(PolyhedronFace *newFace)
Definition: Polyhedron.cc:326
void inet::Polyhedron::cleanConflictGraph ( const Faces conflictVector)
protected

Referenced by buildConvexHull().

276 {
277  for (auto face : conflictVector)
278  {
279 
280  Points& pConflict = face->getConflictVector();
281  for (auto point : pConflict)
282  {
283 
284  Faces& currFConflict = point->getConflictVector();
285  auto fit2 = std::find(currFConflict.begin(), currFConflict.end(), face);
286  if (fit2 == currFConflict.end())
287  throw cRuntimeError("PolyhedronFace not found in the point's conflict vector");
288  currFConflict.erase(fit2);
289  }
290  }
291 }
std::vector< PolyhedronPoint * > Points
Definition: Polyhedron.h:36
std::vector< PolyhedronFace * > Faces
Definition: Polyhedron.h:37
std::vector< T >::iterator find(std::vector< T > &v, const T &a)
Definition: stlutils.h:48
Coord inet::Polyhedron::computeBoundingBoxSize ( ) const
overridevirtual

Computes the 3 dimensional size of the shapes's bounding box.

Implements inet::ShapeBase.

363 {
364  Coord min;
365  Coord max;
366  for (const auto & elem : points)
367  {
368  Coord point = *(elem);
369  min = min.min(point);
370  max = max.max(point);
371  }
372  return max - min;
373 }
double min(const double a, const double b)
Returns the minimum of a and b.
Definition: SCTPAssociation.h:270
Points points
Definition: Polyhedron.h:42
double max(double a, double b)
Returns the greater of the given parameters.
Definition: INETMath.h:161
Polyhedron::Edges inet::Polyhedron::computeHorizonEdges ( const Faces visibleFaces) const
protected

Referenced by buildConvexHull().

171 {
172  Edges horizonEdges;
173  for (Faces::const_iterator it = visibleFaces.begin(); it != visibleFaces.end(); it++)
174  {
175  PolyhedronFace *visibleFace = *it;
176  Edges& edges = visibleFace->getEdges();
177  for (auto visibleEdge : edges)
178  {
179 
180  PolyhedronFace *jointFace = visibleEdge->getJointFace();
181  Faces::const_iterator visibleJointFace = std::find(visibleFaces.begin(), visibleFaces.end(), jointFace);
182  // If the jointFace is not visible then we just have found a horizon edge, that is, a boundary edge
183  // of the visible region from an arbitrary point.
184  // If we found the jointFace among the visibleFaces then we are just examining an inner face.
185  if (visibleJointFace == visibleFaces.end())
186  horizonEdges.push_back(visibleEdge);
187  }
188  }
189  return horizonEdges;
190 }
std::vector< PolyhedronEdge * > Edges
Definition: Polyhedron.h:38
std::vector< T >::iterator find(std::vector< T > &v, const T &a)
Definition: stlutils.h:48
bool inet::Polyhedron::computeIntersection ( const LineSegment lineSegment,
Coord intersection1,
Coord intersection2,
Coord normal1,
Coord normal2 
) const
overridevirtual

Computes the intersection with the given line segment in the shape's coordinate system.

Implements inet::ShapeBase.

376 {
377  // Note: based on http://geomalgorithms.com/a13-_intersect-4.html
378  Coord p0 = lineSegment.getPoint1();
379  Coord p1 = lineSegment.getPoint2();
380  if (p0 == p1)
381  {
382  normal1 = normal2 = Coord::NIL;
383  return false;
384  }
385  Coord segmentDirection = p1 - p0;
386  double tE = 0;
387  double tL = 1;
388  for (auto face : faces)
389  {
390 
391  Coord normalVec = face->getOutwardNormalVector();
392  Coord centroid = face->getCentroid();
393  double N = (centroid - p0) * normalVec;
394  double D = segmentDirection * normalVec;
395  if (D < 0)
396  {
397  double t = N / D;
398  if (t > tE)
399  {
400  tE = t;
401  normal1 = normalVec;
402  if (tE > tL)
403  return false;
404  }
405  }
406  else if (D > 0)
407  {
408  double t = N / D;
409  if (t < tL)
410  {
411  tL = t;
412  normal2 = normalVec;
413  if (tL < tE)
414  return false;
415  }
416  }
417  else
418  {
419  if (N < 0)
420  return false;
421  }
422  }
423  if (tE == 0)
424  normal1 = Coord::NIL;
425  if (tL == 1)
426  normal2 = Coord::NIL;
427  intersection1 = p0 + segmentDirection * tE;
428  intersection2 = p0 + segmentDirection * tL;
429  if (intersection1 == intersection2)
430  {
431  normal1 = normal2 = Coord::NIL;
432  return false;
433  }
434  return true;
435 }
static const Coord NIL
Constant with all values set to 0.
Definition: Coord.h:40
compose< m, compose< kg, pow< s,-2 > > > N
Definition: Units.h:767
Faces faces
Definition: Polyhedron.h:41
PolyhedronPoint inet::Polyhedron::computeOutwardNormalVector ( const PolyhedronFace face) const
protected

Referenced by buildConvexHull(), and generateAndAddTetrahedronFaces().

312 {
313  if (faces.size() <= 0)
314  throw cRuntimeError("You can't compute the outward normal vector if you have no faces at all");
315  PolyhedronFace *testFace = faces.at(0);
316  if (face == testFace)
317  testFace = faces.at(1);
318  Coord testCentroid = testFace->getCentroid();
319  PolyhedronPoint *facePoint = face->getEdge(0)->getP1();
320  Coord faceNormal = face->getNormalVector();
321  if ((testCentroid - *facePoint) * faceNormal > 0)
322  return faceNormal * (-1);
323  return faceNormal;
324 }
Faces faces
Definition: Polyhedron.h:41
void inet::Polyhedron::computeVisibleFaces ( std::vector< std::vector< Coord > > &  faces,
const Rotation rotation,
const Rotation viewRotation 
) const

Referenced by inet::visualizer::PhysicalEnvironmentCanvasVisualizer::refreshDisplay().

438 {
439  for (auto face : this->faces)
440  {
441 
442  if (isVisibleFromView(face, viewRotation, rotation))
443  {
444  const Edges& edges = face->getEdges();
445  std::vector<Coord> points;
446  for (auto edge : edges)
447  {
448 
449  Coord point = *edge->getP1();
450  points.push_back(point);
451  }
452  faces.push_back(points);
453  }
454  }
455 }
std::vector< PolyhedronEdge * > Edges
Definition: Polyhedron.h:38
Points points
Definition: Polyhedron.h:42
bool isVisibleFromView(const PolyhedronFace *face, const Rotation &viewRotation, const Rotation &rotation) const
Definition: Polyhedron.cc:457
Faces faces
Definition: Polyhedron.h:41
void inet::Polyhedron::connectFaces ( PolyhedronFace newFace)
protected

Referenced by buildConvexHull(), and generateAndAddTetrahedronFaces().

327 {
328  Edges& newEdges = newFace->getEdges();
329  for (auto newEdge : newEdges)
330  {
331 
332  for (auto currentFace : faces)
333  {
334 
335  if (currentFace == newFace || currentFace->isWrapped()) continue;
336  PolyhedronEdge *currEdge = currentFace->findEdge(newEdge);
337  if (currEdge)
338  {
339  currEdge->setJointFace(newFace);
340  newEdge->setJointFace(currentFace);
341  }
342  }
343  }
344 }
std::vector< PolyhedronEdge * > Edges
Definition: Polyhedron.h:38
Faces faces
Definition: Polyhedron.h:41
void inet::Polyhedron::createInitialTetrahedron ( )
protected

Referenced by buildConvexHull().

98 {
99  // Initially, we choose four points that do not lie in a common plane, so that their
100  // convex hull is a tetrahedron.
101  auto it = points.begin();
102  PolyhedronPoint *p1 = *it;
103  it++;
104  p1->setToSelected();
105  PolyhedronPoint *p2 = *it;
106  p2->setToSelected();
107  Points tetrahedronPoints;
108  tetrahedronPoints.push_back(p1);
109  tetrahedronPoints.push_back(p2);
110  PolyhedronPoint *p3 = nullptr;
111  it++;
112  while (it != points.end() && !p3)
113  {
114  // Find the point that does not lie on the line through p1 and p2.
115  if (!areCollinear(p1, p2, *it))
116  p3 = *it;
117  else
118  it++;
119  }
120  if (!p3)
121  throw cRuntimeError("All points lie on the same line");
122  p3->setToSelected();
123  tetrahedronPoints.push_back(p3);
124  PolyhedronPoint *p4 = nullptr;
125  it++;
126  while (it != points.end() && !p4)
127  {
128  // Find the point that does not lie in the plane through p1, p2 and p3.
129  if (!areCoplanar(p1, p2, p3, *it))
130  p4 = *it;
131  else
132  it++;
133  }
134  if (!p4)
135  throw cRuntimeError("All points lie in the same plane");
136  tetrahedronPoints.push_back(p4);
137  p4->setToSelected();
138  generateAndAddTetrahedronFaces(tetrahedronPoints);
139 }
bool areCollinear(const PolyhedronPoint *lineP1, const PolyhedronPoint *lineP2, const PolyhedronPoint *point) const
Definition: Polyhedron.cc:83
Points points
Definition: Polyhedron.h:42
std::vector< PolyhedronPoint * > Points
Definition: Polyhedron.h:36
void generateAndAddTetrahedronFaces(const Points &tetrahedronPoints)
Definition: Polyhedron.cc:141
bool areCoplanar(const PolyhedronPoint *p1, const PolyhedronPoint *p2, const PolyhedronPoint *p3, const PolyhedronPoint *p4) const
Definition: Polyhedron.cc:90
void inet::Polyhedron::generateAndAddTetrahedronFaces ( const Points tetrahedronPoints)
protected

Referenced by createInitialTetrahedron().

142 {
143  // We just make CH({p1, p2, p3, p4}), note that, these points are that we have just selected
144  // in crateInitialTetrahedron()
145  PolyhedronFace *face1 = new PolyhedronFace(tetrahedronPoints[0], tetrahedronPoints[1], tetrahedronPoints[2]);
146  PolyhedronFace *face2 = new PolyhedronFace(tetrahedronPoints[0], tetrahedronPoints[1], tetrahedronPoints[3]);
147  PolyhedronFace *face3 = new PolyhedronFace(tetrahedronPoints[0], tetrahedronPoints[2], tetrahedronPoints[3]);
148  PolyhedronFace *face4 = new PolyhedronFace(tetrahedronPoints[1], tetrahedronPoints[2], tetrahedronPoints[3]);
149  // Add the faces to the convex hull
150  addFace(face1);
151  addFace(face2);
152  addFace(face3);
153  addFace(face4);
154  connectFaces(face1);
155  connectFaces(face2);
156  connectFaces(face3);
157  connectFaces(face4);
158  // Calculate the outward normals
159  face1->setOutwardNormalVector(computeOutwardNormalVector(face1));
160  face2->setOutwardNormalVector(computeOutwardNormalVector(face2));
161  face3->setOutwardNormalVector(computeOutwardNormalVector(face3));
162  face4->setOutwardNormalVector(computeOutwardNormalVector(face4));
163 }
PolyhedronPoint computeOutwardNormalVector(const PolyhedronFace *face) const
Definition: Polyhedron.cc:311
void addFace(PolyhedronFace *face)
Definition: Polyhedron.cc:165
void connectFaces(PolyhedronFace *newFace)
Definition: Polyhedron.cc:326
const Faces& inet::Polyhedron::getFaces ( ) const
inline
68 { return faces; }
Faces faces
Definition: Polyhedron.h:41
const Points& inet::Polyhedron::getPoints ( ) const
inline
69 { return points; }
Points points
Definition: Polyhedron.h:42
void inet::Polyhedron::initializeConflictGraph ( )
protected

Referenced by buildConvexHull().

193 {
194  for (auto point : points)
195  {
196 
197  for (auto face : faces)
198  {
199 
200  // The conflict graph is a bipartite graph with point class and face class
201  if (face->isVisibleFrom(point))
202  {
203  point->addConflictFace(face);
204  face->addConflictPoint(point);
205  }
206  }
207  }
208 }
Points points
Definition: Polyhedron.h:42
Faces faces
Definition: Polyhedron.h:41
bool inet::Polyhedron::isVisibleFromView ( const PolyhedronFace face,
const Rotation viewRotation,
const Rotation rotation 
) const
protected

Referenced by computeVisibleFaces().

458 {
459  Coord zNormal(0,0,1);
460  Coord rotatedFaceNormal = viewRotation.rotateVectorClockwise(rotation.rotateVectorClockwise(face->getOutwardNormalVector()));
461  return rotatedFaceNormal * zNormal > 0;
462 }
void inet::Polyhedron::mergeFaces ( PolyhedronFace newFace,
PolyhedronFace neighborFace,
PolyhedronPoint point 
)
protected

Referenced by buildConvexHull().

218 {
219  Edges& edges = neighborFace->getEdges();
220  auto eit = edges.begin();
221  PolyhedronEdge *edge = *eit;
222  // TODO: optimize
223  while (edge->getJointFace() != newFace)
224  {
225  eit++;
226  if (eit == edges.end())
227  throw cRuntimeError("Tried to merge two faces that do not share a common edge");
228  edge = *eit;
229  }
230  // Delete this common edge from the edge vector, but keep its points, next and prev edges to create the merged
231  // face
232  eit = edges.erase(eit);
233  PolyhedronPoint *p1 = edge->getP1();
234  PolyhedronPoint *p2 = edge->getP2();
235  // Create the new edges in neighborFace (we extend neighbor face with newFace (which is a triangular face) to
236  // keep it simple.
237  PolyhedronEdge *edge1 = new PolyhedronEdge(p1, point, neighborFace);
238  PolyhedronEdge *edge2 = new PolyhedronEdge(point, p2, neighborFace);
239  // We must keep the order
240  edges.insert(eit, edge1);
241  eit++;
242  edges.insert(eit, edge2);
243  // Finally, we have to delete the newFace (since we merged and no longer needed) and neighborFace's edge
244  delete newFace;
245  delete edge;
246 }
std::vector< PolyhedronEdge * > Edges
Definition: Polyhedron.h:38
void inet::Polyhedron::purgeConflictFaces ( const Faces conflictVector)
protected

Referenced by buildConvexHull().

303 {
304  for (auto face : conflictVector)
305  {
306 
307  face->setToWrapped();
308  }
309 }
void inet::Polyhedron::purgeWrappedFaces ( )
protected

Referenced by buildConvexHull().

347 {
348  auto fit = faces.begin();
349  while (fit != faces.end())
350  {
351  PolyhedronFace *face = *fit;
352  if (face->isWrapped())
353  {
354  fit = faces.erase(fit);
355  delete face;
356  }
357  else
358  fit++;
359  }
360 }
Faces faces
Definition: Polyhedron.h:41
void inet::Polyhedron::setContlictListForNewFace ( PolyhedronFace newFace,
const PolyhedronFace neighbor1,
const PolyhedronFace neighbor2 
)
protected

Referenced by buildConvexHull().

249 {
250  // Test union of neighbor1's and neighbor2's conflict list
251  std::map<PolyhedronPoint *, bool> visited;
252  const Points& conflict1 = neighbor1->getConflictVector();
253  const Points& conflict2 = neighbor2->getConflictVector();
254  for (const auto & elem : conflict1)
255  {
256  PolyhedronPoint *point = elem;
257  visited.insert(std::pair<PolyhedronPoint *, bool>(point, true));
258  if (newFace->isVisibleFrom(elem))
259  {
260  newFace->addConflictPoint(point);
261  point->addConflictFace(newFace);
262  }
263  }
264  for (auto point : conflict2)
265  {
266 
267  if (visited.find(point) == visited.end() && newFace->isVisibleFrom(point))
268  {
269  point->addConflictFace(newFace);
270  newFace->addConflictPoint(point);
271  }
272  }
273 }
std::vector< PolyhedronPoint * > Points
Definition: Polyhedron.h:36

Member Data Documentation


The documentation for this class was generated from the following files: