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 RotationMatrix &rotation, const RotationMatrix &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 RotationMatrix &viewRotation, const RotationMatrix &rotation) const
 

Protected Attributes

Faces faces
 
Points points
 

Member Typedef Documentation

◆ Edges

typedef std::vector<PolyhedronEdge *> inet::Polyhedron::Edges

◆ Faces

typedef std::vector<PolyhedronFace *> inet::Polyhedron::Faces

◆ Points

typedef std::vector<PolyhedronPoint *> inet::Polyhedron::Points

Constructor & Destructor Documentation

◆ Polyhedron()

inet::Polyhedron::Polyhedron ( const std::vector< Coord > &  points)
258 {
259  if (points.size() < 4)
260  throw cRuntimeError("We need at least four points");
261  for (const auto& point : points)
262  this->points.push_back(new PolyhedronPoint(point));
263  buildConvexHull();
264 }

◆ ~Polyhedron()

inet::Polyhedron::~Polyhedron ( )
virtual
404 {
405  for (auto& elem : points)
406  delete elem;
407  for (auto& elem : faces)
408  delete elem;
409 }

Member Function Documentation

◆ addFace()

void inet::Polyhedron::addFace ( PolyhedronFace face)
protected
150 {
151  faces.push_back(face);
152 }

Referenced by buildConvexHull(), and generateAndAddTetrahedronFaces().

◆ areCollinear()

bool inet::Polyhedron::areCollinear ( const PolyhedronPoint lineP1,
const PolyhedronPoint lineP2,
const PolyhedronPoint point 
) const
protected
70 {
71  PolyhedronPoint P1P2 = *lineP2 - *lineP1;
72  PolyhedronPoint P1Point = *point - *lineP1;
73  return P1P2 % P1Point == Coord(0, 0, 0);
74 }

Referenced by createInitialTetrahedron().

◆ areCoplanar() [1/2]

bool inet::Polyhedron::areCoplanar ( const PolyhedronFace face1,
const PolyhedronFace face2 
) const
protected
185 {
186  Coord faceNormal1 = face1->getNormalVector();
187  Coord faceNormal2 = face2->getNormalVector();
188  return faceNormal1 % faceNormal2 == Coord(0, 0, 0);
189 }

◆ areCoplanar() [2/2]

bool inet::Polyhedron::areCoplanar ( const PolyhedronPoint p1,
const PolyhedronPoint p2,
const PolyhedronPoint p3,
const PolyhedronPoint p4 
) const
protected
77 {
78  // http://mathworld.wolfram.com/Coplanar.html
79  // The volume of the tetrahedron they define.
80  return (*p3 - *p1) * ((*p2 - *p1) % (*p4 - *p3)) == 0;
81 }

Referenced by buildConvexHull(), and createInitialTetrahedron().

◆ buildConvexHull()

void inet::Polyhedron::buildConvexHull ( )
protected
23 {
25 // std::random_shuffle(points.begin(), points.end());
27  for (auto currentPoint : points) {
28  if (currentPoint->isSelected())
29  continue;
30  currentPoint->setToSelected();
31  // If there is no conflicts then the point is already contained in the current convex hull
32  if (currentPoint->hasConflicts()) {
33  // Delete all faces in currentPoint conflict vector from the hull
34  Faces& conflictVector = currentPoint->getConflictVector();
35  Faces copyConflictVector = currentPoint->getConflictVector();
36  purgeConflictFaces(conflictVector);
37  // Computes a closed curve consisting of edges of the current convex hull
38  // This closed curve can be interpreted as the border of the visible region from our current point
39  Edges horizonEdges = computeHorizonEdges(conflictVector);
40  for (auto horizonEdge : horizonEdges) {
41  // Faces incident to horizonEdge in the current convex hull
42  PolyhedronFace *neighborFace = horizonEdge->getJointFace();
43  PolyhedronFace *parentFace = horizonEdge->getParentFace();
44  // Connect horizonEdge to currentPoint by creating a triangular face newFace
45  PolyhedronFace *newFace = new PolyhedronFace(horizonEdge->getP1(), horizonEdge->getP2(), currentPoint);
46  // Coplanar faces have to be merged together since they define a bigger face
47  // Due to these merges the computeIntersection() algorithm will have to visit fewer faces
48  // It is clear that conflict list and outward normals are same as that of neighborFace
49  connectFaces(newFace); // TODO optimize
50  if (areCoplanar(newFace, neighborFace)) {
51  mergeFaces(newFace, neighborFace, currentPoint);
52  connectFaces(neighborFace);
53  }
54  else {
55  // If they are not coplanar we just add it to the faces and compute its outward normal vector
56  // and update the conflict graph
57  newFace->setOutwardNormalVector(computeOutwardNormalVector(newFace));
58  addFace(newFace);
59  setContlictListForNewFace(newFace, neighborFace, parentFace);
60  }
61  }
62  // We have to delete the old faces that wrapped by the new faces
63  cleanConflictGraph(copyConflictVector);
64  }
65  }
67 }

Referenced by Polyhedron().

◆ cleanConflictGraph()

void inet::Polyhedron::cleanConflictGraph ( const Faces conflictVector)
protected
244 {
245  for (auto face : conflictVector) {
246  Points& pConflict = face->getConflictVector();
247  for (auto point : pConflict) {
248  Faces& currFConflict = point->getConflictVector();
249  auto fit2 = find(currFConflict, face);
250  if (fit2 == currFConflict.end())
251  throw cRuntimeError("PolyhedronFace not found in the point's conflict vector");
252  currFConflict.erase(fit2);
253  }
254  }
255 }

Referenced by buildConvexHull().

◆ computeBoundingBoxSize()

Coord inet::Polyhedron::computeBoundingBoxSize ( ) const
overridevirtual

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

Implements inet::ShapeBase.

317 {
318  Coord min;
319  Coord max;
320  for (const auto& elem : points) {
321  Coord point = *(elem);
322  min = min.min(point);
323  max = max.max(point);
324  }
325  return max - min;
326 }

◆ computeHorizonEdges()

Polyhedron::Edges inet::Polyhedron::computeHorizonEdges ( const Faces visibleFaces) const
protected
155 {
156  Edges horizonEdges;
157  for (Faces::const_iterator it = visibleFaces.begin(); it != visibleFaces.end(); it++) {
158  PolyhedronFace *visibleFace = *it;
159  Edges& edges = visibleFace->getEdges();
160  for (auto visibleEdge : edges) {
161  // If the jointFace is not visible then we just have found a horizon edge, that is, a boundary edge
162  // of the visible region from an arbitrary point.
163  // If we found the jointFace among the visibleFaces then we are just examining an inner face.
164  if (!contains(visibleFaces, visibleEdge->getJointFace()))
165  horizonEdges.push_back(visibleEdge);
166  }
167  }
168  return horizonEdges;
169 }

Referenced by buildConvexHull().

◆ computeIntersection()

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.

329 {
330  // Note: based on http://geomalgorithms.com/a13-_intersect-4.html
331  Coord p0 = lineSegment.getPoint1();
332  Coord p1 = lineSegment.getPoint2();
333  if (p0 == p1) {
334  normal1 = normal2 = Coord::NIL;
335  return false;
336  }
337  Coord segmentDirection = p1 - p0;
338  double tE = 0;
339  double tL = 1;
340  for (auto face : faces) {
341  Coord normalVec = face->getOutwardNormalVector();
342  Coord centroid = face->getCentroid();
343  double N = (centroid - p0) * normalVec;
344  double D = segmentDirection * normalVec;
345  if (D < 0) {
346  double t = N / D;
347  if (t > tE) {
348  tE = t;
349  normal1 = normalVec;
350  if (tE > tL)
351  return false;
352  }
353  }
354  else if (D > 0) {
355  double t = N / D;
356  if (t < tL) {
357  tL = t;
358  normal2 = normalVec;
359  if (tL < tE)
360  return false;
361  }
362  }
363  else {
364  if (N < 0)
365  return false;
366  }
367  }
368  if (tE == 0)
369  normal1 = Coord::NIL;
370  if (tL == 1)
371  normal2 = Coord::NIL;
372  intersection1 = p0 + segmentDirection * tE;
373  intersection2 = p0 + segmentDirection * tL;
374  if (intersection1 == intersection2) {
375  normal1 = normal2 = Coord::NIL;
376  return false;
377  }
378  return true;
379 }

◆ computeOutwardNormalVector()

PolyhedronPoint inet::Polyhedron::computeOutwardNormalVector ( const PolyhedronFace face) const
protected
273 {
274  if (faces.size() <= 0)
275  throw cRuntimeError("You can't compute the outward normal vector if you have no faces at all");
276  PolyhedronFace *testFace = faces.at(0);
277  if (face == testFace)
278  testFace = faces.at(1);
279  Coord testCentroid = testFace->getCentroid();
280  PolyhedronPoint *facePoint = face->getEdge(0)->getP1();
281  Coord faceNormal = face->getNormalVector();
282  if ((testCentroid - *facePoint) * faceNormal > 0)
283  return faceNormal * (-1);
284  return faceNormal;
285 }

Referenced by buildConvexHull(), and generateAndAddTetrahedronFaces().

◆ computeVisibleFaces()

void inet::Polyhedron::computeVisibleFaces ( std::vector< std::vector< Coord >> &  faces,
const RotationMatrix rotation,
const RotationMatrix viewRotation 
) const
382 {
383  for (auto face : this->faces) {
384  if (isVisibleFromView(face, viewRotation, rotation)) {
385  const Edges& edges = face->getEdges();
386  std::vector<Coord> points;
387  for (auto edge : edges) {
388  Coord point = *edge->getP1();
389  points.push_back(point);
390  }
391  faces.push_back(points);
392  }
393  }
394 }

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

◆ connectFaces()

void inet::Polyhedron::connectFaces ( PolyhedronFace newFace)
protected
288 {
289  Edges& newEdges = newFace->getEdges();
290  for (auto newEdge : newEdges) {
291  for (auto currentFace : faces) {
292  if (currentFace == newFace || currentFace->isWrapped()) continue;
293  PolyhedronEdge *currEdge = currentFace->findEdge(newEdge);
294  if (currEdge) {
295  currEdge->setJointFace(newFace);
296  newEdge->setJointFace(currentFace);
297  }
298  }
299  }
300 }

Referenced by buildConvexHull(), and generateAndAddTetrahedronFaces().

◆ createInitialTetrahedron()

void inet::Polyhedron::createInitialTetrahedron ( )
protected
84 {
85  // Initially, we choose four points that do not lie in a common plane, so that their
86  // convex hull is a tetrahedron.
87  auto it = points.begin();
88  PolyhedronPoint *p1 = *it;
89  it++;
90  p1->setToSelected();
91  PolyhedronPoint *p2 = *it;
92  p2->setToSelected();
93  Points tetrahedronPoints;
94  tetrahedronPoints.push_back(p1);
95  tetrahedronPoints.push_back(p2);
96  PolyhedronPoint *p3 = nullptr;
97  it++;
98  while (it != points.end() && !p3) {
99  // Find the point that does not lie on the line through p1 and p2.
100  if (!areCollinear(p1, p2, *it))
101  p3 = *it;
102  else
103  it++;
104  }
105  if (!p3)
106  throw cRuntimeError("All points lie on the same line");
107  p3->setToSelected();
108  tetrahedronPoints.push_back(p3);
109  PolyhedronPoint *p4 = nullptr;
110  it++;
111  while (it != points.end() && !p4) {
112  // Find the point that does not lie in the plane through p1, p2 and p3.
113  if (!areCoplanar(p1, p2, p3, *it))
114  p4 = *it;
115  else
116  it++;
117  }
118  if (!p4)
119  throw cRuntimeError("All points lie in the same plane");
120  tetrahedronPoints.push_back(p4);
121  p4->setToSelected();
122  generateAndAddTetrahedronFaces(tetrahedronPoints);
123 }

Referenced by buildConvexHull().

◆ generateAndAddTetrahedronFaces()

void inet::Polyhedron::generateAndAddTetrahedronFaces ( const Points tetrahedronPoints)
protected
126 {
127  // We just make CH({p1, p2, p3, p4}), note that, these points are that we have just selected
128  // in crateInitialTetrahedron()
129  PolyhedronFace *face1 = new PolyhedronFace(tetrahedronPoints[0], tetrahedronPoints[1], tetrahedronPoints[2]);
130  PolyhedronFace *face2 = new PolyhedronFace(tetrahedronPoints[0], tetrahedronPoints[1], tetrahedronPoints[3]);
131  PolyhedronFace *face3 = new PolyhedronFace(tetrahedronPoints[0], tetrahedronPoints[2], tetrahedronPoints[3]);
132  PolyhedronFace *face4 = new PolyhedronFace(tetrahedronPoints[1], tetrahedronPoints[2], tetrahedronPoints[3]);
133  // Add the faces to the convex hull
134  addFace(face1);
135  addFace(face2);
136  addFace(face3);
137  addFace(face4);
138  connectFaces(face1);
139  connectFaces(face2);
140  connectFaces(face3);
141  connectFaces(face4);
142  // Calculate the outward normals
143  face1->setOutwardNormalVector(computeOutwardNormalVector(face1));
144  face2->setOutwardNormalVector(computeOutwardNormalVector(face2));
145  face3->setOutwardNormalVector(computeOutwardNormalVector(face3));
146  face4->setOutwardNormalVector(computeOutwardNormalVector(face4));
147 }

Referenced by createInitialTetrahedron().

◆ getFaces()

const Faces& inet::Polyhedron::getFaces ( ) const
inline

◆ getPoints()

const Points& inet::Polyhedron::getPoints ( ) const
inline
59 { return points; }

◆ initializeConflictGraph()

void inet::Polyhedron::initializeConflictGraph ( )
protected
172 {
173  for (auto point : points) {
174  for (auto face : faces) {
175  // The conflict graph is a bipartite graph with point class and face class
176  if (face->isVisibleFrom(point)) {
177  point->addConflictFace(face);
178  face->addConflictPoint(point);
179  }
180  }
181  }
182 }

Referenced by buildConvexHull().

◆ isVisibleFromView()

bool inet::Polyhedron::isVisibleFromView ( const PolyhedronFace face,
const RotationMatrix viewRotation,
const RotationMatrix rotation 
) const
protected
397 {
398  Coord zNormal(0, 0, 1);
399  Coord rotatedFaceNormal = viewRotation.rotateVector(rotation.rotateVector(face->getOutwardNormalVector()));
400  return rotatedFaceNormal * zNormal > 0;
401 }

Referenced by computeVisibleFaces().

◆ mergeFaces()

void inet::Polyhedron::mergeFaces ( PolyhedronFace newFace,
PolyhedronFace neighborFace,
PolyhedronPoint point 
)
protected
192 {
193  Edges& edges = neighborFace->getEdges();
194  auto eit = edges.begin();
195  PolyhedronEdge *edge = *eit;
196  // TODO optimize
197  while (edge->getJointFace() != newFace) {
198  eit++;
199  if (eit == edges.end())
200  throw cRuntimeError("Tried to merge two faces that do not share a common edge");
201  edge = *eit;
202  }
203  // Delete this common edge from the edge vector, but keep its points, next and prev edges to create the merged
204  // face
205  eit = edges.erase(eit);
206  PolyhedronPoint *p1 = edge->getP1();
207  PolyhedronPoint *p2 = edge->getP2();
208  // Create the new edges in neighborFace (we extend neighbor face with newFace (which is a triangular face) to
209  // keep it simple.
210  PolyhedronEdge *edge1 = new PolyhedronEdge(p1, point, neighborFace);
211  PolyhedronEdge *edge2 = new PolyhedronEdge(point, p2, neighborFace);
212  // We must keep the order
213  edges.insert(eit, edge1);
214  eit++;
215  edges.insert(eit, edge2);
216  // Finally, we have to delete the newFace (since we merged and no longer needed) and neighborFace's edge
217  delete newFace;
218  delete edge;
219 }

Referenced by buildConvexHull().

◆ purgeConflictFaces()

void inet::Polyhedron::purgeConflictFaces ( const Faces conflictVector)
protected
267 {
268  for (auto face : conflictVector)
269  face->setToWrapped();
270 }

Referenced by buildConvexHull().

◆ purgeWrappedFaces()

void inet::Polyhedron::purgeWrappedFaces ( )
protected
303 {
304  auto fit = faces.begin();
305  while (fit != faces.end()) {
306  PolyhedronFace *face = *fit;
307  if (face->isWrapped()) {
308  fit = faces.erase(fit);
309  delete face;
310  }
311  else
312  fit++;
313  }
314 }

Referenced by buildConvexHull().

◆ setContlictListForNewFace()

void inet::Polyhedron::setContlictListForNewFace ( PolyhedronFace newFace,
const PolyhedronFace neighbor1,
const PolyhedronFace neighbor2 
)
protected
222 {
223  // Test union of neighbor1's and neighbor2's conflict list
224  std::map<PolyhedronPoint *, bool> visited;
225  const Points& conflict1 = neighbor1->getConflictVector();
226  const Points& conflict2 = neighbor2->getConflictVector();
227  for (const auto& elem : conflict1) {
228  PolyhedronPoint *point = elem;
229  visited.insert(std::pair<PolyhedronPoint *, bool>(point, true));
230  if (newFace->isVisibleFrom(elem)) {
231  newFace->addConflictPoint(point);
232  point->addConflictFace(newFace);
233  }
234  }
235  for (auto point : conflict2) {
236  if (!containsKey(visited, point) && newFace->isVisibleFrom(point)) {
237  point->addConflictFace(newFace);
238  newFace->addConflictPoint(point);
239  }
240  }
241 }

Referenced by buildConvexHull().

Member Data Documentation

◆ faces

◆ points


The documentation for this class was generated from the following files:
inet::Polyhedron::areCollinear
bool areCollinear(const PolyhedronPoint *lineP1, const PolyhedronPoint *lineP2, const PolyhedronPoint *point) const
Definition: Polyhedron.cc:69
inet::Polyhedron::Points
std::vector< PolyhedronPoint * > Points
Definition: Polyhedron.h:26
inet::Polyhedron::points
Points points
Definition: Polyhedron.h:32
inet::Polyhedron::faces
Faces faces
Definition: Polyhedron.h:31
inet::sctp::min
double min(const double a, const double b)
Returns the minimum of a and b.
Definition: SctpAssociation.h:261
inet::find
std::vector< T >::iterator find(std::vector< T > &v, const Tk &a)
Definition: stlutils.h:44
inet::units::units::N
compose< m, compose< kg, pow< s, -2 > > > N
Definition: Units.h:936
inet::Polyhedron::createInitialTetrahedron
void createInitialTetrahedron()
Definition: Polyhedron.cc:83
inet::Polyhedron::connectFaces
void connectFaces(PolyhedronFace *newFace)
Definition: Polyhedron.cc:287
inet::Polyhedron::Faces
std::vector< PolyhedronFace * > Faces
Definition: Polyhedron.h:27
inet::Polyhedron::addFace
void addFace(PolyhedronFace *face)
Definition: Polyhedron.cc:149
inet::contains
bool contains(const std::vector< T > &v, const Tk &a)
Definition: stlutils.h:65
inet::Polyhedron::computeOutwardNormalVector
PolyhedronPoint computeOutwardNormalVector(const PolyhedronFace *face) const
Definition: Polyhedron.cc:272
inet::Polyhedron::Edges
std::vector< PolyhedronEdge * > Edges
Definition: Polyhedron.h:28
inet::Polyhedron::generateAndAddTetrahedronFaces
void generateAndAddTetrahedronFaces(const Points &tetrahedronPoints)
Definition: Polyhedron.cc:125
inet::Polyhedron::mergeFaces
void mergeFaces(PolyhedronFace *newFace, PolyhedronFace *neighborFace, PolyhedronPoint *point)
Definition: Polyhedron.cc:191
inet::sctp::max
double max(const double a, const double b)
Returns the maximum of a and b.
Definition: SctpAssociation.h:266
inet::Polyhedron::buildConvexHull
void buildConvexHull()
Definition: Polyhedron.cc:22
inet::Polyhedron::areCoplanar
bool areCoplanar(const PolyhedronPoint *p1, const PolyhedronPoint *p2, const PolyhedronPoint *p3, const PolyhedronPoint *p4) const
Definition: Polyhedron.cc:76
inet::Polyhedron::purgeWrappedFaces
void purgeWrappedFaces()
Definition: Polyhedron.cc:302
inet::Polyhedron::cleanConflictGraph
void cleanConflictGraph(const Faces &conflictVector)
Definition: Polyhedron.cc:243
inet::Coord::NIL
static const Coord NIL
Constant with all values set to 0.
Definition: Coord.h:26
inet::Polyhedron::computeHorizonEdges
Edges computeHorizonEdges(const Faces &visibleFaces) const
Definition: Polyhedron.cc:154
inet::Polyhedron::initializeConflictGraph
void initializeConflictGraph()
Definition: Polyhedron.cc:171
inet::Polyhedron::isVisibleFromView
bool isVisibleFromView(const PolyhedronFace *face, const RotationMatrix &viewRotation, const RotationMatrix &rotation) const
Definition: Polyhedron.cc:396
inet::Polyhedron::setContlictListForNewFace
void setContlictListForNewFace(PolyhedronFace *newFace, const PolyhedronFace *neighbor1, const PolyhedronFace *neighbor2)
Definition: Polyhedron.cc:221
inet::Polyhedron::purgeConflictFaces
void purgeConflictFaces(const Faces &conflictVector)
Definition: Polyhedron.cc:266
inet::containsKey
bool containsKey(const std::map< K, V, _C > &m, const Tk &a)
Definition: stlutils.h:80