Main MRPT website > C++ reference
MRPT logo
CPolyhedron.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | The Mobile Robot Programming Toolkit (MRPT) C++ library |
3  | |
4  | http://www.mrpt.org/ |
5  | |
6  | Copyright (C) 2005-2012 University of Malaga |
7  | |
8  | This software was written by the Machine Perception and Intelligent |
9  | Robotics Lab, University of Malaga (Spain). |
10  | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
11  | |
12  | This file is part of the MRPT project. |
13  | |
14  | MRPT is free software: you can redistribute it and/or modify |
15  | it under the terms of the GNU General Public License as published by |
16  | the Free Software Foundation, either version 3 of the License, or |
17  | (at your option) any later version. |
18  | |
19  | MRPT is distributed in the hope that it will be useful, |
20  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
21  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22  | GNU General Public License for more details. |
23  | |
24  | You should have received a copy of the GNU General Public License |
25  | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
26  | |
27  +---------------------------------------------------------------------------+ */
28 #ifndef opengl_CPolyhedron_H
29 #define opengl_CPolyhedron_H
30 
33 #include <mrpt/math/geometry.h>
34 
35 namespace mrpt {
36 namespace opengl {
37  using namespace mrpt::utils;
38  using namespace mrpt::poses;
39  using namespace std;
40 
42 
43  // This must be added to any CSerializable derived class:
45  /**
46  * This class represents arbitrary polyhedra. The class includes a set of static methods to create common polyhedrons. The class includes many methods to create standard polyhedra, not intended to be fast but to be simple. For example, the dodecahedron is not created efficiently: first, an icosahedron is created, and a duality operator is applied to it, which yields the dodecahedron. This way, code is much smaller, although much slower. This is not a big problem, since polyhedron creation does not usually take a significant amount of time (they are created once and rendered many times).
47  * Polyhedra information and models have been gotten from the Wikipedia, http://wikipedia.org
48  * \sa opengl::COpenGLScene
49  *
50  * <div align="center">
51  * <table border="0" cellspan="4" cellspacing="4" style="border-width: 1px; border-style: solid;">
52  * <tr> <td> mrpt::opengl::CPolyhedron </td> <td> \image html preview_CPolyhedron.png </td> </tr>
53  * </table>
54  * </div>
55  *
56  * \ingroup mrpt_opengl_grp
57  */
60  public:
61  /**
62  * Struct used to store a polyhedron edge. The struct consists only of two vertex indices, used to access the polyhedron vertex list.
63  */
65  /**
66  * First vertex.
67  */
68  uint32_t v1;
69  /**
70  * Second vertex.
71  */
72  uint32_t v2;
73  /**
74  * Default constructor. Initializes to garbage.
75  */
76  TPolyhedronEdge():v1(),v2() {}
77  /**
78  * Comparison agains another edge. Simmetry is taken into account.
79  */
80  bool operator==(const TPolyhedronEdge &e) const {
81  if (e.v1==v1&&e.v2==v2) return true;
82  else return e.v1==v2&&e.v2==v1;
83  }
84  /**
85  * Given a set of vertices, computes the length of the vertex.
86  */
87  double length(const vector<TPoint3D> &vs) const;
88  /**
89  * Destructor.
90  */
92  };
93  /**
94  * Struct used to store a polyhedron face. Consists on a set of vertex indices and a normal vector.
95  */
97  /**
98  * Vector of indices to the vertex list.
99  */
100  vector<uint32_t> vertices;
101  /**
102  * Normal vector.
103  */
104  double normal[3];
105  /**
106  * Fast default constructor. Initializes to garbage.
107  */
108  TPolyhedronFace():vertices() {}
109  /**
110  * Destructor.
111  */
113  /**
114  * Given a set of vertices, computes the area of this face.
115  */
116  double area(const vector<TPoint3D> &vertices) const;
117  /**
118  * Given a set of vertices, get this face's center.
119  */
120  void getCenter(const vector<TPoint3D> &vertices,TPoint3D &p) const;
121  };
122  protected:
123  /**
124  * List of vertices presents in the polyhedron.
125  */
126  vector<TPoint3D> mVertices;
127  /**
128  * List of polyhedron's edges.
129  */
130  vector<TPolyhedronEdge> mEdges;
131  /**
132  * List of polyhedron's faces.
133  */
134  vector<TPolyhedronFace> mFaces;
135  /**
136  * This flag determines whether the polyhedron will be displayed as a solid object or as a set of edges.
137  */
139  /**
140  * When displaying as wireframe object, this variable stores the width of the edges.
141  */
142  double mLineWidth;
143  /**
144  * Mutable list of actual polygons, maintained for speed.
145  */
146  mutable std::vector<TPolygonWithPlane> tempPolygons;
147  /**
148  * Whether the set of actual polygons is up to date or not.
149  */
150  mutable bool polygonsUpToDate;
151  public:
152  /**
153  * Creation of a polyhedron from its vertices and faces.
154  * \throw logic_error if the polyhedron definition has flaws (bad vertex indices, etc.).
155  */
156  inline static CPolyhedronPtr Create(const vector<TPoint3D> &vertices,const vector<vector<uint32_t> > &faces) {
157  vector<TPolyhedronFace> aux;
158  for (vector<vector<uint32_t> >::const_iterator it=faces.begin();it!=faces.end();++it) {
159  TPolyhedronFace f;
160  f.vertices=*it;
161  aux.push_back(f);
162  }
163  return Create(vertices,aux);
164  }
165  /**
166  * Creation of a polyhedron from its vertices and faces.
167  * \throw logic_error if the polyhedron definition has flaws (bad vertex indices, etc.).
168  */
169  inline static CPolyhedronPtr Create(const vector<TPoint3D> &vertices,const vector<TPolyhedronFace> &faces) {
170  return CPolyhedronPtr(new CPolyhedron(vertices,faces,true));
171  }
172  /**
173  * Creation from a set of polygons.
174  * \sa mrpt::math::TPolygon3D
175  */
176  static CPolyhedronPtr Create(const std::vector<math::TPolygon3D> &polys);
177 
178  //Static methods to create frequent polyhedra. More bizarre polyhedra are intended to be added in a near future.
179 
180  /** @name Platonic solids.
181  @{
182  */
183  /**
184  * Creates a regular tetrahedron (see http://en.wikipedia.org/wiki/Tetrahedron). The tetrahedron is created as a triangular pyramid whose edges and vertices are transitive.
185  * The tetrahedron is the dual to itself.
186  <p align="center"><img src="Tetrahedron.gif"></p>
187  * \sa CreatePyramid,CreateJohnsonSolidWithConstantBase,CreateTruncatedTetrahedron
188  */
189  inline static CPolyhedronPtr CreateTetrahedron(double radius) {
190  CPolyhedronPtr tetra=CreateJohnsonSolidWithConstantBase(3,radius*sqrt(8.0)/3.0,"P+");
191  for (vector<TPoint3D>::iterator it=tetra->mVertices.begin();it!=tetra->mVertices.end();++it) it->z-=radius/3;
192  return tetra;
193  }
194  /**
195  * Creates a regular cube, also called hexahedron (see http://en.wikipedia.org/wiki/Hexahedron). The hexahedron is created as a cubic prism which transitive edges. Another ways to create it include:
196  <ul><li>Dual to an octahedron.</li><li>Parallelepiped with three orthogonal, equally-lengthed vectors.</li><li>Triangular trapezohedron with proper height.</li></ul>
197  <p align="center"><img src="Hexahedron.gif"></p>
198  * \sa CreateOctahedron,getDual,CreateParallelepiped,CreateTrapezohedron,CreateTruncatedHexahedron,CreateTruncatedOctahedron,CreateCuboctahedron,CreateRhombicuboctahedron
199  */
200  inline static CPolyhedronPtr CreateHexahedron(double radius) {
201  if (radius==0.0) return CreateEmpty();
202  double r=radius/sqrt(3.0);
203  return CreateCubicPrism(-r,r,-r,r,-r,r);
204  }
205  /**
206  * Creates a regular octahedron (see http://en.wikipedia.org/wiki/Octahedron). The octahedron is created as a square bipyramid whit transitive edges and vertices. Another ways to create an octahedron are:
207  <ul><li>Dual to an hexahedron</li><li>Triangular antiprism with transitive vertices.</li><li>Conveniently truncated tetrahedron.</li></ul>
208  <p align="center"><img src="Octahedron.gif"></p>
209  * \sa CreateHexahedron,getDual,CreateArchimedeanAntiprism,CreateTetrahedron,truncate,CreateTruncatedOctahedron,CreateTruncatedHexahedron,CreateCuboctahedron,CreateRhombicuboctahedron
210  */
211  inline static CPolyhedronPtr CreateOctahedron(double radius) {
212  return CreateJohnsonSolidWithConstantBase(4,radius,"P-P+");
213  }
214  /**
215  * Creates a regular dodecahedron (see http://en.wikipedia.org/wiki/Dodecahedron). The dodecahedron is created as the dual to an icosahedron.
216  <p align="center"><img src="Dodecahedron.gif"></p>
217  * \sa CreateIcosahedron,getDual,CreateTruncatedDodecahedron,CreateTruncatedIcosahedron,CreateIcosidodecahedron,CreateRhombicosidodecahedron
218  */
219  inline static CPolyhedronPtr CreateDodecahedron(double radius) {
220  return CreateIcosahedron(radius/sqrt(15-6*sqrt(5.0)))->getDual();
221  }
222  /**
223  * Creates a regular icosahedron (see http://en.wikipedia.org/wiki/Icosahedron). The icosahedron is created as a gyroelongated pentagonal bipyramid with transitive edges, and it's the dual to a dodecahedron.
224  <p align="center"><img src="Icosahedron.gif"></p>
225  * \sa CreateJohnsonSolidWithConstantBase,CreateDodecahedron,getDual,CreateTruncatedIcosahedron,CreateTruncatedDodecahedron,CreateIcosidodecahedron,CreateRhombicosidodecahedron
226  */
227  inline static CPolyhedronPtr CreateIcosahedron(double radius) {
228  double ang=M_PI/5;
229  double s2=4*square(sin(ang));
230  double prop=sqrt(s2-1)+sqrt(s2-2+2*cos(ang))/2;
231  return CreateJohnsonSolidWithConstantBase(5,radius/prop,"P-AP+",1);
232  }
233  /** @}
234  */
235 
236  /** @name Archimedean solids.
237  @{
238  */
239  /**
240  * Creates a truncated tetrahedron, consisting of four triangular faces and for hexagonal ones (see http://en.wikipedia.org/wiki/Truncated_tetrahedron). Its dual is the triakis tetrahedron.
241  <p align="center"><img src="Truncatedtetrahedron.gif"></p>
242  * \sa CreateTetrahedron,CreateTriakisTetrahedron
243  */
244  inline static CPolyhedronPtr CreateTruncatedTetrahedron(double radius) {
245  return CreateTetrahedron(radius*sqrt(27.0/11.0))->truncate(2.0/3.0);
246  }
247  /**
248  * Creates a cuboctahedron, consisting of six square faces and eight triangular ones (see http://en.wikipedia.org/wiki/Cuboctahedron). There are several ways to create a cuboctahedron:
249  <ul><li>Hexahedron truncated to a certain extent.</li><li>Octahedron truncated to a certain extent.</li><li>Cantellated tetrahedron</li><li>Dual to a rhombic dodecahedron.</li></ul>
250  <p align="center"><img src="Cuboctahedron.gif"></p>
251  * \sa CreateHexahedron,CreateOctahedron,truncate,CreateTetrahedron,cantellate,CreateRhombicuboctahedron,CreateRhombicDodecahedron,
252  */
253  inline static CPolyhedronPtr CreateCuboctahedron(double radius) {
254  return CreateHexahedron(radius*sqrt(1.5))->truncate(1.0);
255  }
256  /**
257  * Creates a truncated hexahedron, with six octogonal faces and eight triangular ones (see http://en.wikipedia.org/wiki/Truncated_hexahedron). The truncated octahedron is dual to the triakis octahedron.
258  <p align="center"><img src="Truncatedhexahedron.gif"></p>
259  * \sa CreateHexahedron,CreateTriakisOctahedron
260  */
261  inline static CPolyhedronPtr CreateTruncatedHexahedron(double radius) {
262  return CreateHexahedron(radius*sqrt(3.0/(5-sqrt(8.0))))->truncate(2-sqrt(2.0));
263  }
264  /**
265  * Creates a truncated octahedron, with eight hexagons and eight squares (see http://en.wikipedia.org/wiki/Truncated_octahedron). It's the dual to the tetrakis hexahedron.
266  <p align="center"><img src="Truncatedoctahedron.gif"></p>
267  * \sa CreateOctahedron,CreateTetrakisHexahedron
268  */
269  inline static CPolyhedronPtr CreateTruncatedOctahedron(double radius) {
270  return CreateOctahedron(radius*3/sqrt(5.0))->truncate(2.0/3.0);
271  }
272  /**
273  * Creates a rhombicuboctahedron, with 18 squares and 8 triangles (see http://en.wikipedia.org/wiki/Rhombicuboctahedron), calculated as an elongated square bicupola. It can also be calculated as a cantellated hexahedron or octahedron, and its dual is the deltoidal icositetrahedron.
274  * If the second argument is set to false, the lower cupola is rotated, so that the objet created is an elongated square gyrobicupola (see http://en.wikipedia.org/wiki/Elongated_square_gyrobicupola). This is not an archimedean solid, but a Johnson one, since it hasn't got vertex transitivity.
275  <p align="center"><img src="Rhombicuboctahedron.gif"></p>
276  * \sa CreateJohnsonSolidWithConstantBase,CreateHexahedron,CreateOctahedron,cantellate,CreateCuboctahedron,CreateDeltoidalIcositetrahedron
277  */
278  inline static CPolyhedronPtr CreateRhombicuboctahedron(double radius,bool type=true) {
279  return CreateJohnsonSolidWithConstantBase(8,radius/sqrt(1+square(sin(M_PI/8))),type?"C-PRC+":"GC-PRC+",3);
280  }
281  /**
282  * Creates an icosidodecahedron, with 12 pentagons and 20 triangles (see http://en.wikipedia.org/wiki/Icosidodecahedron). Certain truncations of either a dodecahedron or an icosahedron yield an icosidodecahedron.
283  * The dual of the icosidodecahedron is the rhombic triacontahedron.
284  * If the second argument is set to false, the lower rotunda is rotated. In this case, the object created is a pentagonal orthobirotunda (see http://en.wikipedia.org/wiki/Pentagonal_orthobirotunda). This object presents symmetry against the XY plane and is not vertex transitive, so it's a Johnson's solid.
285  <p align="center"><img src="Icosidodecahedron.gif"></p>
286  * \sa CreateDodecahedron,CreateIcosahedron,truncate,CreateRhombicosidodecahedron,CreateRhombicTriacontahedron
287  */
288  inline static CPolyhedronPtr CreateIcosidodecahedron(double radius,bool type=true) {
289  return CreateJohnsonSolidWithConstantBase(10,radius,type?"GR-R+":"R-R+",1);
290  }
291  /**
292  * Creates a truncated dodecahedron, consisting of 12 dodecagons and 20 triangles (see http://en.wikipedia.org/wiki/Truncated_dodecahedron). The truncated dodecahedron is the dual to the triakis icosahedron.
293  <p align="center"><img src="Truncateddodecahedron.gif"></p>
294  * \sa CreateDodecahedron,CreateTriakisIcosahedron
295  */
296  inline static CPolyhedronPtr CreateTruncatedDodecahedron(double radius) {
297  return CreateDodecahedron(radius*sqrt(45.0)/sqrt(27+6*sqrt(5.0)))->truncate(1-sqrt(0.2));
298  }
299  /**
300  * Creates a truncated icosahedron, consisting of 20 hexagons and 12 pentagons. This object resembles a typical soccer ball (see http://en.wikipedia.org/wiki/Truncated_icosahedron). The pentakis dodecahedron is the dual to the truncated icosahedron.
301  <p align="center"><img src="Truncatedicosahedron.gif"></p>
302  * \sa CreateIcosahedron,CreatePentakisDodecahedron
303  */
304  inline static CPolyhedronPtr CreateTruncatedIcosahedron(double radius) {
305  return CreateIcosahedron(radius*sqrt(45.0)/sqrt(25+4*sqrt(5.0)))->truncate(2.0/3.0);
306  }
307  /**
308  * Creates a rhombicosidodecahedron, consisting of 30 squares, 12 pentagons and 20 triangles (see http://en.wikipedia.org/wiki/Rhombicosidodecahedron). This object can be obtained as the cantellation of either a dodecahedron or an icosahedron. The dual of the rhombicosidodecahedron is the deltoidal hexecontahedron.
309  <p align="center"><img src="Rhombicosidodecahedron.gif"></p>
310  * \sa CreateDodecahedron,CreateIcosahedron,CreateIcosidodecahedron,CreateDeltoidalHexecontahedron
311  */
312  inline static CPolyhedronPtr CreateRhombicosidodecahedron(double radius) {
313  return CreateIcosahedron(radius*sqrt(10.0/(35.0+9.0*sqrt(5.0))))->cantellate(1.5*(sqrt(5.0)-1));
314  }
315  /** @}
316  */
317 
318  /** @name Other Johnson solids.
319  @{
320  */
321  /**
322  * Creates a pentagonal rotunda (half an icosidodecahedron), consisting of six pentagons, ten triangles and a decagon (see http://en.wikipedia.org/wiki/Pentagonal_rotunda).
323  * \sa CreateIcosidodecahedron,CreateJohnsonSolidWithConstantBase
324  */
325  inline static CPolyhedronPtr CreatePentagonalRotunda(double radius) {
326  return CreateJohnsonSolidWithConstantBase(10,radius,"R+");
327  }
328  /** @}
329  */
330 
331  /** @name Catalan solids.
332  @{
333  */
334  /**
335  * Creates a triakis tetrahedron, dual to the truncated tetrahedron. This body consists of 12 isosceles triangles (see http://en.wikipedia.org/wiki/Triakis_tetrahedron).
336  <p align="center"><img src="Triakistetrahedron.gif"></p>
337  * \sa CreateTruncatedTetrahedron
338  */
339  inline static CPolyhedronPtr CreateTriakisTetrahedron(double radius) {
340  return CreateTruncatedTetrahedron(radius*3/sqrt(33.0))->getDual();
341  }
342 
343  /**
344  * Creates a rhombic dodecahedron, dual to the cuboctahedron. This body consists of 12 rhombi (see http://en.wikipedia.org/wiki/Rhombic_dodecahedron).
345  <p align="center"><img src="Rhombicdodecahedron.gif"></p>
346  * \sa CreateCuboctahedron
347  */
348  inline static CPolyhedronPtr CreateRhombicDodecahedron(double radius) {
349  return CreateCuboctahedron(radius/sqrt(2.0))->getDual();
350  }
351 
352  /**
353  * Creates a triakis octahedron, dual to the truncated hexahedron. This body consists of 24 isosceles triangles (see http://en.wikipedia.org/wiki/Triakis_octahedron).
354  <p align="center"><img src="Triakisoctahedron.gif"></p>
355  * \sa CreateTruncatedHexahedron
356  */
357  inline static CPolyhedronPtr CreateTriakisOctahedron(double radius) {
358  return CreateTruncatedHexahedron(radius/sqrt((5-sqrt(8.0))))->getDual();
359  }
360 
361  /**
362  * Creates a tetrakis hexahedron, dual to the truncated octahedron. This body consists of 24 isosceles triangles (see http://en.wikipedia.org/wiki/Tetrakis_hexahedron).
363  <p align="center"><img src="Tetrakishexahedron.gif"></p>
364  * \sa CreateTruncatedOctahedron
365  */
366  inline static CPolyhedronPtr CreateTetrakisHexahedron(double radius) {
367  return CreateTruncatedOctahedron(radius*sqrt(0.6))->getDual();
368  }
369 
370  /**
371  * Creates a deltoidal icositetrahedron, dual to the rhombicuboctahedron. This body consists of 24 kites (see http://en.wikipedia.org/wiki/Deltoidal_icositetrahedron).
372  <p align="center"><img src="Deltoidalicositetrahedron.gif"></p>
373  * \sa CreateRhombicuboctahedron
374  */
375  inline static CPolyhedronPtr CreateDeltoidalIcositetrahedron(double radius) {
376  return CreateRhombicuboctahedron(radius/sqrt(7-sqrt(32.0)),true)->getDual();
377  }
378 
379  /**
380  * Creates a rhombic triacontahedron, dual to the icosidodecahedron. This body consists of 30 rhombi (see http://en.wikipedia.org/wiki/Rhombic_triacontahedron).
381  <p align="center"><img src="Rhombictriacontahedron.gif"></p>
382  * \sa CreateIcosidodecahedron
383  */
384  inline static CPolyhedronPtr CreateRhombicTriacontahedron(double radius) {
385  return CreateIcosidodecahedron(radius*sqrt(2/(5-sqrt(5.0))),true)->getDual();
386  }
387 
388  /**
389  * Creates a triakis icosahedron, dual to the truncated dodecahedron. This body consists of 60 isosceles triangles http://en.wikipedia.org/wiki/Triakis_icosahedron).
390  <p align="center"><img src="Triakisicosahedron.gif"></p>
391  * \sa CreateTruncatedDodecahedron
392  */
393  inline static CPolyhedronPtr CreateTriakisIcosahedron(double radius) {
394  return CreateTruncatedDodecahedron(radius*sqrt(5/(25-8*sqrt(5.0))))->getDual();
395  }
396 
397  /**
398  * Creates a pentakis dodecahedron, dual to the truncated icosahedron. This body consists of 60 isosceles triangles (see http://en.wikipedia.org/wiki/Pentakis_dodecahedron).
399  <p align="center"><img src="Pentakisdodecahedron.gif"></p>
400  * \sa CreateTruncatedIcosahedron
401  */
402  inline static CPolyhedronPtr CreatePentakisDodecahedron(double radius) {
403  return CreateTruncatedIcosahedron(radius*sqrt(3/(17-6*sqrt(5.0))))->getDual();
404  }
405 
406  /**
407  * Creates a deltoidal hexecontahedron, dual to the rhombicosidodecahedron. This body consists of 60 kites (see http://en.wikipedia.org/wiki/Deltoidal_hexecontahedron).
408  <p align="center"><img src="Deltoidalhexecontahedron.gif"></p>
409  * \sa CreateRhombicosidodecahedron
410  */
411  inline static CPolyhedronPtr CreateDeltoidalHexecontahedron(double radius) {
412  return CreateRhombicosidodecahedron(radius*3.0/sqrt(15-2*sqrt(5.0)))->getDual();
413  }
414  /** @}
415  */
416 
417  /** @name Customizable polyhedra
418  @{
419  */
420  /**
421  * Creates a cubic prism, given the coordinates of two opposite vertices. Each edge will be parallel to one of the coordinate axes, although the orientation may change by assigning a pose to the object.
422  * \sa CreateCubicPrism(const mrpt::math::TPoint3D &,const mrpt::math::TPoint3D &),CreateParallelepiped,CreateCustomPrism,CreateRegularPrism,CreateArchimedeanRegularPrism
423  */
424  static CPolyhedronPtr CreateCubicPrism(double x1,double x2,double y1,double y2,double z1,double z2);
425  /**
426  * Creates a cubic prism, given two opposite vertices.
427  * \sa CreateCubicPrism(double,double,double,double,double,double),CreateParallelepiped,CreateCustomPrism,CreateRegularPrism,CreateArchimedeanRegularPrism
428  */
429  inline static CPolyhedronPtr CreateCubicPrism(const TPoint3D &p1,const TPoint3D &p2) {
430  return CreateCubicPrism(p1.x,p2.x,p1.y,p2.y,p1.z,p2.z);
431  }
432  /**
433  * Creates a custom pyramid, using a set of 2D vertices which will lie on the XY plane.
434  * \sa CreateDoublePyramid,CreateFrustum,CreateBifrustum,CreateRegularPyramid
435  */
436  static CPolyhedronPtr CreatePyramid(const vector<TPoint2D> &baseVertices,double height);
437  /**
438  * Creates a double pyramid, using a set of 2D vertices which will lie on the XY plane. The second height is used with the downwards pointing pyramid, so that it will effectively point downwards if it's positive.
439  * \sa CreatePyramid,CreateBifrustum,CreateRegularDoublePyramid
440  */
441  static CPolyhedronPtr CreateDoublePyramid(const vector<TPoint2D> &baseVertices,double height1,double height2);
442  /**
443  * Creates a truncated pyramid, using a set of vertices which will lie on the XY plane.
444  * Do not try to use with a ratio equal to zero; use CreatePyramid instead. When using a ratio of 1, it will create a Prism.
445  * \sa CreatePyramid,CreateBifrustum
446  */
447  static CPolyhedronPtr CreateTruncatedPyramid(const vector<TPoint2D> &baseVertices,double height,double ratio);
448  /**
449  * This is a synonym for CreateTruncatedPyramid.
450  * \sa CreateTruncatedPyramid
451  */
452  inline static CPolyhedronPtr CreateFrustum(const vector<TPoint2D> &baseVertices,double height,double ratio) {
453  return CreateTruncatedPyramid(baseVertices,height,ratio);
454  }
455  /**
456  * Creates a custom prism with vertical edges, given any base which will lie on the XY plane.
457  * \sa CreateCubicPrism,CreateCustomAntiprism,CreateRegularPrism,CreateArchimedeanRegularPrism
458  */
459  inline static CPolyhedronPtr CreateCustomPrism(const vector<TPoint2D> &baseVertices,double height) {
460  return CreateTruncatedPyramid(baseVertices,height,1.0);
461  }
462  /**
463  * Creates a custom antiprism, using two custom bases. For better results, the top base should be slightly rotated with respect to the bottom one.
464  * \sa CreateCustomPrism,CreateRegularAntiprism,CreateArchimedeanRegularAntiprism
465  */
466  static CPolyhedronPtr CreateCustomAntiprism(const vector<TPoint2D> &bottomBase,const vector<TPoint2D> &topBase,double height);
467  /**
468  * Creates a parallelepiped, given a base point and three vectors represented as points.
469  * \sa CreateCubicPrism
470  */
471  static CPolyhedronPtr CreateParallelepiped(const TPoint3D &base,const TPoint3D &v1,const TPoint3D &v2,const TPoint3D &v3);
472  /**
473  * Creates a bifrustum, or double truncated pyramid, given a base which will lie on the XY plane.
474  * \sa CreateFrustum,CreateDoublePyramid
475  */
476  static CPolyhedronPtr CreateBifrustum(const vector<TPoint2D> &baseVertices,double height1,double ratio1,double height2,double ratio2);
477  /**
478  * Creates a trapezohedron, consisting of 2*N kites, where N is the number of edges in the base. The base radius controls the polyhedron height, whilst the distance between bases affects the height.
479  * When the number of edges equals 3, the polyhedron is actually a parallelepiped, and it can even be a cube.
480  */
481  static CPolyhedronPtr CreateTrapezohedron(uint32_t numBaseEdges,double baseRadius,double basesDistance);
482  /**
483  * Creates an antiprism whose base is a regular polygon. The upper base is rotated \f$\frac\pi N\f$ with respect to the lower one, where N is the number of vertices in the base, and thus the lateral triangles are isosceles.
484  * \sa CreateCustomAntiprism,CreateArchimedeanRegularAntiprism
485  */
486  inline static CPolyhedronPtr CreateRegularAntiprism(uint32_t numBaseEdges,double baseRadius,double height) {
487  return CreateCustomAntiprism(generateBase(numBaseEdges,baseRadius),generateShiftedBase(numBaseEdges,baseRadius),height);
488  }
489  /**
490  * Creates a regular prism whose base is a regular polygon and whose edges are either parallel or perpendicular to the XY plane.
491  * \sa CreateCubicPrism,CreateCustomPrism,CreateArchimedeanRegularAntiprism
492  */
493  inline static CPolyhedronPtr CreateRegularPrism(uint32_t numBaseEdges,double baseRadius,double height) {
494  return CreateCustomPrism(generateBase(numBaseEdges,baseRadius),height);
495  }
496  /**
497  * Creates a regular pyramid whose base is a regular polygon.
498  * \sa CreatePyramid
499  */
500  inline static CPolyhedronPtr CreateRegularPyramid(uint32_t numBaseEdges,double baseRadius,double height) {
501  return CreatePyramid(generateBase(numBaseEdges,baseRadius),height);
502  }
503  /**
504  * Creates a regular double pyramid whose base is a regular polygon.
505  * \sa CreateDoublePyramid
506  */
507  inline static CPolyhedronPtr CreateRegularDoublePyramid(uint32_t numBaseEdges,double baseRadius,double height1,double height2) {
508  return CreateDoublePyramid(generateBase(numBaseEdges,baseRadius),height1,height2);
509  }
510  /**
511  * Creates a regular prism whose lateral area is comprised of squares, and so each face of its is a regular polygon. Due to vertex transitivity, the resulting object is always archimedean.
512  * \sa CreateRegularPrism,CreateCustomPrism
513  */
514  inline static CPolyhedronPtr CreateArchimedeanRegularPrism(uint32_t numBaseEdges,double baseRadius) {
515  return CreateJohnsonSolidWithConstantBase(numBaseEdges,baseRadius,"PR");
516  }
517  /**
518  * Creates a regular antiprism whose lateral polygons are equilateral triangles, and so each face of its is a regular polygon. Due to vertex transitivity, the resulting object is always archimedean.
519  * \sa CreateRegularAntiprism,CreateCustomAntiprism
520  */
521  inline static CPolyhedronPtr CreateArchimedeanRegularAntiprism(uint32_t numBaseEdges,double baseRadius) {
522  return CreateJohnsonSolidWithConstantBase(numBaseEdges,baseRadius,"A");
523  }
524  /**
525  * Creates a regular truncated pyramid whose base is a regular polygon.
526  * \sa CreateTruncatedPyramid
527  */
528  inline static CPolyhedronPtr CreateRegularTruncatedPyramid(uint32_t numBaseEdges,double baseRadius,double height,double ratio) {
529  return CreateTruncatedPyramid(generateBase(numBaseEdges,baseRadius),height,ratio);
530  }
531  /**
532  * This is a synonym for CreateRegularTruncatedPyramid.
533  * \sa CreateRegularTruncatedPyramid
534  */
535  inline static CPolyhedronPtr CreateRegularFrustum(uint32_t numBaseEdges,double baseRadius,double height,double ratio) {
536  return CreateRegularTruncatedPyramid(numBaseEdges,baseRadius,height,ratio);
537  }
538  /**
539  * Creates a bifrustum (double truncated pyramid) whose base is a regular polygon lying in the XY plane.
540  * \sa CreateBifrustum
541  */
542  inline static CPolyhedronPtr CreateRegularBifrustum(uint32_t numBaseEdges,double baseRadius,double height1,double ratio1,double height2,double ratio2) {
543  return CreateBifrustum(generateBase(numBaseEdges,baseRadius),height1,ratio1,height2,ratio2);
544  }
545  /**
546  * Creates a cupola.
547  * \throw std::logic_error if the number of edges is odd or less than four.
548  */
549  inline static CPolyhedronPtr CreateCupola(uint32_t numBaseEdges,double edgeLength) {
550  return CreateJohnsonSolidWithConstantBase(numBaseEdges,edgeLength/(2*sin(M_PI/numBaseEdges)),"C+");
551  }
552  /**
553  * Creates a trapezohedron whose dual is exactly an archimedean antiprism. Creates a cube if numBaseEdges is equal to 3.
554  * \todo Actually resulting height is significantly higher than that passed to the algorithm.
555  * \sa CreateTrapezohedron,CreateArchimedeanRegularAntiprism,getDual
556  */
557  inline static CPolyhedronPtr CreateCatalanTrapezohedron(uint32_t numBaseEdges,double height) {
558  return CreateArchimedeanRegularAntiprism(numBaseEdges,height)->getDual();
559  }
560  /**
561  * Creates a double pyramid whose dual is exactly an archimedean prism. Creates an octahedron if numBaseEdges is equal to 4.
562  * \todo Actually resulting height is significantly higher than that passed to the algorithm.
563  * \sa CreateDoublePyramid,CreateArchimedeanRegularPrism,getDual
564  */
565  inline static CPolyhedronPtr CreateCatalanDoublePyramid(uint32_t numBaseEdges,double height) {
566  return CreateArchimedeanRegularPrism(numBaseEdges,height)->getDual();
567  }
568  /**
569  * Creates a series of concatenated solids (most of which are prismatoids) whose base is a regular polygon with a given number of edges. Every face of the resulting body will be a regular polygon, so it is a Johnson solid; in special cases, it may be archimedean or even platonic.
570  * The shape of the body is defined by the string argument, which can include one or more of the following:
571  <center><table>
572  <tr><td><b>String</b></td><td><b>Body</b></td><td><b>Restrictions</b></td></tr>
573  <tr><td>P+</td><td>Upward pointing pyramid</td><td>Must be the last object, vertex number cannot surpass 5</td></tr>
574  <tr><td>P-</td><td>Downward pointing pyramid</td><td>Must be the first object, vertex number cannot surpass 5</td></tr>
575  <tr><td>C+</td><td>Upward pointing cupola</td><td>Must be the last object, vertex number must be an even number in the range 4-10.</td></tr>
576  <tr><td>C-</td><td>Downward pointing cupola</td><td>Must be the first object, vertex number must be an even number in the range 4-10.</td></tr>
577  <tr><td>GC+</td><td>Upward pointing cupola, rotated</td><td>Must be the last object, vertex number must be an even number in the range 4-10.</td></tr>
578  <tr><td>GC-</td><td>Downward pointing cupola, rotated</td><td>Must be the first object, vertex number must be an even number in the range 4-10.</td></tr>
579  <tr><td>PR</td><td>Archimedean prism</td><td>Cannot abut other prism</td></tr>
580  <tr><td>A</td><td>Archimedean antiprism</td><td>None</td></tr>
581  <tr><td>R+</td><td>Upward pointing rotunda</td><td>Must be the last object, vertex number must be exactly 10</td></tr>
582  <tr><td>R-</td><td>Downward pointing rotunda</td><td>Must be the first object, vertex number must be exactly 10</td></tr>
583  <tr><td>GR+</td><td>Upward pointing rotunda, rotated</td><td>Must be the last object, vertex number must be exactly 10</td></tr>
584  <tr><td>GR-</td><td>Downward pointing rotunda</td><td>Must be the first object, vertex number must be exactly 10</td></tr>
585  </table></center>
586  * Some examples of bodies are:
587  <center><table>
588  <tr><td><b>String</b></td><td><b>Vertices</b></td><td><b>Resulting body</b></td></tr>
589  <tr><td>P+</td><td align="center">3</td><td>Tetrahedron</td></tr>
590  <tr><td>PR</td><td align="center">4</td><td>Hexahedron</td></tr>
591  <tr><td>P-P+</td><td align="center">4</td><td>Octahedron</td></tr>
592  <tr><td>A</td><td align="center">3</td><td>Octahedron</td></tr>
593  <tr><td>C+PRC-</td><td align="center">8</td><td>Rhombicuboctahedron</td></tr>
594  <tr><td>P-AP+</td><td align="center">5</td><td>Icosahedron</td></tr>
595  <tr><td>R-R+</td><td align="center">10</td><td>Icosidodecahedron</td></tr>
596  </table></center>
597  */
598  static CPolyhedronPtr CreateJohnsonSolidWithConstantBase(uint32_t numBaseEdges,double baseRadius,const std::string &components,size_t shifts=0);
599  /** @}
600  */
601 
602  /**
603  * Render
604  * \sa CRenderizable
605  */
606  void render_dl() const;
607  /**
608  * Ray trace
609  * \sa CRenderizable
610  */
611  virtual bool traceRay(const mrpt::poses::CPose3D &o,double &dist) const;
612  /**
613  * Gets a list with the polyhedron's vertices.
614  */
615  inline void getVertices(vector<TPoint3D> &vertices) const {
616  vertices=mVertices;
617  }
618  /**
619  * Gets a list with the polyhedron's edges.
620  */
621  inline void getEdges(vector<TPolyhedronEdge> &edges) const {
622  edges=mEdges;
623  }
624  /**
625  * Gets a list with the polyhedron's faces.
626  */
627  inline void getFaces(vector<TPolyhedronFace> &faces) const {
628  faces=mFaces;
629  }
630  /**
631  * Gets the amount of vertices.
632  */
633  inline uint32_t getNumberOfVertices() const {
634  return mVertices.size();
635  }
636  /**
637  * Gets the amount of edges.
638  */
639  inline uint32_t getNumberOfEdges() const {
640  return mEdges.size();
641  }
642  /**
643  * Gets the amount of faces.
644  */
645  inline uint32_t getNumberOfFaces() const {
646  return mFaces.size();
647  }
648  /**
649  * Gets a vector with each edge's length.
650  */
651  void getEdgesLength(vector<double> &lengths) const;
652  /**
653  * Gets a vector with each face's area. Won't work properly if the polygons are not convex.
654  */
655  void getFacesArea(vector<double> &areas) const;
656  /**
657  * Gets the polyhedron volume. Won't work properly if the polyhedron is not convex.
658  */
659  double getVolume() const;
660  /**
661  * Returns whether the polyhedron will be rendered as a wireframe object.
662  */
663  inline bool isWireframe() const {
664  return mWireframe;
665  }
666  /**
667  * Sets whether the polyhedron will be rendered as a wireframe object.
668  */
669  inline void setWireframe(bool enabled=true) {
670  mWireframe=enabled;
672  }
673  /**
674  * Gets the wireframe lines width.
675  */
676  inline double getLineWidth() const {
677  return mLineWidth;
678  }
679  /**
680  * Sets the width used to render lines, when wireframe rendering is activated.
681  */
682  inline void setLineWidth(double lineWidth) {
683  mLineWidth=lineWidth;
685  }
686  /**
687  * Gets the polyhedron as a set of polygons.
688  * \sa mrpt::math::TPolygon3D
689  */
690  void getSetOfPolygons(std::vector<math::TPolygon3D> &vec) const;
691  /**
692  * Gets the polyhedron as a set of polygons, with the pose transformation already applied.
693  * \sa mrpt::math::TPolygon3D,mrpt::poses::CPose3D
694  */
695  void getSetOfPolygonsAbsolute(std::vector<math::TPolygon3D> &vec) const;
696  /**
697  * Gets the intersection of two polyhedra, either as a set or as a matrix of intersections. Each intersection is represented by a TObject3D.
698  * \sa mrpt::math::TObject3D
699  */
700  template<class T> inline static size_t getIntersection(const CPolyhedronPtr &p1,const CPolyhedronPtr &p2,T &container) {
701  std::vector<TPolygon3D> polys1,polys2;
702  p1->getSetOfPolygonsAbsolute(polys1);
703  p2->getSetOfPolygonsAbsolute(polys2);
704  return mrpt::math::intersect(polys1,polys2,container);
705  }
706  /**
707  * Returns true if the polygon is a completely closed object.
708  */
709  inline bool isClosed() const {
710  for (size_t i=0;i<mVertices.size();i++) if (edgesInVertex(i)!=facesInVertex(i)) return false;
711  return true;
712  }
713  /**
714  * Recomputes polygons, if necessary, so that each one is convex.
715  */
716  void makeConvexPolygons();
717  /**
718  * Gets the center of the polyhedron.
719  */
720  void getCenter(TPoint3D &center) const;
721  /**
722  * Creates a random polyhedron from the static methods.
723  */
724  static CPolyhedronPtr CreateRandomPolyhedron(double radius);
725 
726  /** @name Polyhedron special operations.
727  @{
728  */
729  /**
730  * Given a polyhedron, creates its dual.
731  * \sa truncate,cantellate,augment
732  * \throw std::logic_error Can't get the dual to this polyhedron.
733  */
734  CPolyhedronPtr getDual() const;
735  /**
736  * Truncates a polyhedron to a given factor.
737  * \sa getDual,cantellate,augment
738  * \throw std::logic_error Polyhedron truncation results in skew polygons and thus it's impossible to perform.
739  */
740  CPolyhedronPtr truncate(double factor) const;
741  /**
742  * Cantellates a polyhedron to a given factor.
743  * \sa getDual,truncate,augment
744  */
745  CPolyhedronPtr cantellate(double factor) const;
746  /**
747  * Augments a polyhedron to a given height. This operation is roughly dual to the truncation: given a body P, the operation dtdP and aP yield resembling results.
748  * \sa getDual,truncate,cantellate
749  */
750  CPolyhedronPtr augment(double height) const;
751  /**
752  * Augments a polyhedron to a given height. This method only affects to faces with certain number of vertices.
753  * \sa augment(double) const
754  */
755  CPolyhedronPtr augment(double height,size_t numVertices) const;
756  /**
757  * Augments a polyhedron, so that the resulting triangles are equilateral. If the argument is true, triangles are "cut" from the polyhedron, instead of being added.
758  * \throw std::logic_error a non-regular face has been found.
759  * \sa augment(double) const
760  */
761  CPolyhedronPtr augment(bool direction=false) const;
762  /**
763  * Augments a polyhedron, so that the resulting triangles are equilateral; affects only faces with certain number of faces. If the second argument is true, triangles are "cut" from the polyhedron.
764  * \throw std::logic_error a non-regular face has been found.
765  * \sa augment(double) const
766  */
767  CPolyhedronPtr augment(size_t numVertices,bool direction=false) const;
768  /**
769  * Rotates a polyhedron around the Z axis a given amount of radians. In some cases, this operation may be necessary to view the symmetry between related objects.
770  * \sa scale
771  */
772  CPolyhedronPtr rotate(double angle) const;
773  /**
774  * Scales a polyhedron to a given factor.
775  * \throw std::logic_error factor is not a strictly positive number.
776  * \sa rotate
777  */
778  CPolyhedronPtr scale(double factor) const;
779  /** @}
780  */
781  /**
782  * Updates the mutable list of polygons used in rendering and ray tracing.
783  */
784  void updatePolygons() const;
785  private:
786  /**
787  * Generates a list of 2D vertices constituting a regular polygon.
788  */
789  static vector<TPoint2D> generateBase(uint32_t numBaseEdges,double baseRadius);
790  /**
791  * Generates a list of 2D vertices constituting a regular polygon, with an angle shift which makes it suitable for antiprisms.
792  */
793  static vector<TPoint2D> generateShiftedBase(uint32_t numBaseEdges,double baseRadius);
794  /**
795  * Generates a list of 3D vertices constituting a regular polygon, appending it to an existing vector.
796  */
797  static void generateBase(uint32_t numBaseEdges,double baseRadius,double height,vector<TPoint3D> &vec);
798  /**
799  * Generates a list of 3D vertices constituting a regular polygon conveniently shifted, appending it to an existing vector.
800  */
801  static void generateShiftedBase(uint32_t numBaseEdges,double baseRadius,double height,double shift,vector<TPoint3D> &vec);
802  /**
803  * Calculates the normal vector to a face.
804  */
805  bool setNormal(TPolyhedronFace &f,bool doCheck=true);
806  /**
807  * Adds, to the existing list of edges, each edge in a given face.
808  */
809  void addEdges(const TPolyhedronFace &e);
810  /**
811  * Checks whether a set of faces is suitable for a set of vertices.
812  */
813  static bool checkConsistence(const vector<TPoint3D> &vertices,const vector<TPolyhedronFace> &faces);
814  /**
815  * Returns how many edges converge in a given vertex.
816  */
817  size_t edgesInVertex(size_t vertex) const;
818  /**
819  * Returns how many faces converge in a given vertex.
820  */
821  size_t facesInVertex(size_t vertex) const;
822  /**
823  * Basic empty constructor.
824  */
825  inline CPolyhedron():mVertices(),mEdges(),mFaces(),mWireframe(false),mLineWidth(1),polygonsUpToDate(false) {}
826  /**
827  * Basic constructor with a list of vertices and another of faces, checking for correctness.
828  */
829  inline CPolyhedron(const vector<TPoint3D> &vertices,const vector<TPolyhedronFace> &faces,bool doCheck=true):mVertices(vertices),mEdges(),mFaces(faces),mWireframe(false),mLineWidth(1),polygonsUpToDate(false) {
830  if (doCheck) if (!checkConsistence(vertices,faces)) throw std::logic_error("Face list accesses a vertex out of range");
831  for (vector<TPolyhedronFace>::iterator it=mFaces.begin();it!=mFaces.end();++it) {
832  if (!setNormal(*it,doCheck)) throw std::logic_error("Bad face specification");
833  addEdges(*it);
834  }
835  }
836  /**
837  * Creates a polyhedron without checking its correctness.
838  */
839  inline static CPolyhedronPtr CreateNoCheck(const vector<TPoint3D> &vertices,const vector<TPolyhedronFace> &faces) {
840  return CPolyhedronPtr(new CPolyhedron(vertices,faces,false));
841  }
842  /**
843  * Creates an empty Polyhedron.
844  */
845  inline static CPolyhedronPtr CreateEmpty() {
846  return CPolyhedronPtr(new CPolyhedron());
847  }
848  /**
849  * Destructor.
850  */
851  virtual ~CPolyhedron() {}
852  };
853  /**
854  * Reads a polyhedron edge from a binary stream.
855  */
856  OPENGL_IMPEXP mrpt::utils::CStream& operator>>(mrpt::utils::CStream& in,CPolyhedron::TPolyhedronEdge &o);
857  /**
858  * Writes a polyhedron edge to a binary stream.
859  */
860  OPENGL_IMPEXP mrpt::utils::CStream& operator<<(mrpt::utils::CStream& out,const CPolyhedron::TPolyhedronEdge &o);
861  /**
862  * Reads a polyhedron face from a binary stream.
863  */
864  OPENGL_IMPEXP mrpt::utils::CStream& operator>>(mrpt::utils::CStream& in,CPolyhedron::TPolyhedronFace &o);
865  /**
866  * Writes a polyhedron face to a binary stream.
867  */
868  OPENGL_IMPEXP mrpt::utils::CStream& operator<<(mrpt::utils::CStream& out,const CPolyhedron::TPolyhedronFace &o);
869 }
870  namespace utils {
871  using namespace mrpt::opengl;
872  // Specialization must occur in the same namespace
873  MRPT_DECLARE_TTYPENAME(CPolyhedron::TPolyhedronEdge)
874  MRPT_DECLARE_TTYPENAME(CPolyhedron::TPolyhedronFace)
875  }
876 }
877 #endif



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013