Main MRPT website > C++ reference for MRPT 1.9.9
CPolyhedron.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "opengl-precomp.h" // Precompiled header
13 #include <mrpt/math/CMatrix.h>
14 #include <mrpt/poses/CPose3D.h>
15 #include <mrpt/math/geometry.h>
16 #include <mrpt/math/ops_containers.h> // dotProduct()
17 #include <mrpt/random.h>
18 #include <mrpt/utils/CStream.h>
20 
21 #include "opengl_internals.h"
22 
23 using namespace mrpt;
24 using namespace mrpt::math;
25 using namespace mrpt::opengl;
26 using namespace mrpt::utils;
27 using namespace mrpt::poses;
28 using namespace std;
29 
31 
32 // Auxiliary data and code
33 template <class T>
35 {
36  public:
37  const vector<TPoint3D>& verts;
38  FCreatePolygonFromFace(const vector<TPoint3D>& v) : verts(v) {}
41  {
42  p = TPolygon3D(f.vertices.size());
43  for (size_t i = 0; i < f.vertices.size(); i++)
44  p[i] = verts[f.vertices[i]];
45  return p;
46  }
47 };
48 
50  const vector<math::TPolygon3D>& polys, vector<TPoint3D>& vertices,
51  vector<CPolyhedron::TPolyhedronFace>& faces)
52 {
53  vertices.reserve(4 * polys.size());
54  faces.reserve(polys.size());
55  for (std::vector<math::TPolygon3D>::const_iterator it = polys.begin();
56  it != polys.end(); ++it)
57  {
58  size_t N = it->size();
59  if (N < 3) return false;
61  f.vertices.resize(N);
62  for (size_t i = 0; i < N; i++)
63  {
65  find(vertices.begin(), vertices.end(), (*it)[i]);
66  if (it2 == vertices.end())
67  {
68  f.vertices[i] = vertices.size();
69  vertices.push_back((*it)[i]);
70  }
71  else
72  f.vertices[i] = it2 - vertices.begin();
73  }
74  faces.push_back(f);
75  }
76  return true;
77 }
78 
80 {
89  PRISM = 6,
90  ANTIPRISM = 7,
95 };
97  const std::string& components, uint32_t numBaseEdges,
98  vector<JohnsonBodyPart>& parts)
99 {
100  size_t N = components.length();
101  size_t i = 0;
102  bool rot = false;
103  while (i < N)
104  {
105  switch (components[i])
106  {
107  case 'A':
108  case 'a':
109  if (parts.size() == 0) parts.push_back(INF_NO_BODY);
110  parts.push_back(ANTIPRISM);
111  break;
112  case 'C':
113  case 'c':
114  if (numBaseEdges & 1) return false;
115  if (i == N - 1) return false;
116  i++;
117  if (components[i] == '+')
118  {
119  if (i != N - 1) return false;
120  if (parts.size() == 0) parts.push_back(INF_NO_BODY);
121  parts.push_back(
123  rot = false;
124  }
125  else if (components[i] == '-')
126  {
127  if (parts.size() > 0) return false;
128  parts.push_back(
130  rot = false;
131  }
132  else
133  return false;
134  break;
135  case 'R':
136  case 'r':
137  if (numBaseEdges != 10) return false;
138  if (i == N - 1) return false;
139  i++;
140  if (components[i] == '+')
141  {
142  if (i != N - 1) return false;
143  if (parts.size() == 0) parts.push_back(INF_NO_BODY);
144  parts.push_back(
146  rot = false;
147  }
148  else if (components[i] == '-')
149  {
150  if (parts.size() > 0) return false;
151  parts.push_back(
153  rot = false;
154  }
155  else
156  return false;
157  break;
158  case 'G':
159  case 'g':
160  if (i == N - 1) return false;
161  i++;
162  if (components[i] == 'C' || components[i] == 'R')
163  {
164  rot = true;
165  continue;
166  }
167  else
168  return false;
169  case 'P':
170  case 'p':
171  if (i == N - 1) return false;
172  i++;
173  switch (components[i])
174  {
175  case '+':
176  if (numBaseEdges > 5) return false;
177  if (i != N - 1) return false;
178  if (parts.size() == 0) parts.push_back(INF_NO_BODY);
179  parts.push_back(UPWARDS_PYRAMID);
180  break;
181  case '-':
182  if (numBaseEdges > 5) return false;
183  if (i != 1) return false;
184  parts.push_back(DOWNWARDS_PYRAMID);
185  break;
186  case 'R':
187  case 'r':
188  if (parts.size() > 0 && (*parts.rbegin() == PRISM))
189  return false;
190  if (parts.size() == 0) parts.push_back(INF_NO_BODY);
191  parts.push_back(PRISM);
192  break;
193  default:
194  return false;
195  }
196  break;
197  default:
198  return false;
199  }
200  i++;
201  }
202  if (parts.size() == 0) return false;
203  JohnsonBodyPart p = *parts.rbegin();
204  if (p != UPWARDS_PYRAMID && p != UPWARDS_CUPOLA &&
207  parts.push_back(SUP_NO_BODY);
208  return true;
209 }
210 inline size_t additionalVertices(JohnsonBodyPart j, uint32_t numBaseEdges)
211 {
212  if (j == INF_NO_BODY || j == SUP_NO_BODY)
213  return 0;
214  else if (j < UPWARDS_CUPOLA)
215  return 1; // j is a pyramid
216  else if (j < PRISM)
217  return numBaseEdges >> 1; // j is a cupola
218  else if (j < UPWARDS_ROTUNDA)
219  return numBaseEdges; // j is a prism or antiprism
220  else
221  return 10; // j is a rotunda
222 }
224  size_t numBaseEdges, double angleShift, double baseRadius,
225  double edgeLength, bool isRotated, bool isUpwards, size_t base,
226  vector<TPoint3D>& verts, vector<CPolyhedron::TPolyhedronFace>& faces)
227 {
228  size_t edges2 = numBaseEdges >> 1;
229  double minorRadius =
230  baseRadius * sin(M_PI / numBaseEdges) / sin(M_PI / edges2);
231  //"Proper base"'s apothem=base radius*cos(2*pi/(2*numBaseEdges))
232  //"Small base"'s apothem=small radius*cos(2*pi/2*(numBaseEdges/2))
233  // Cupola's height is so that (Da^2+Height^2=Edge length^2, where Da is the
234  // difference between both apothems.
235  double h = sqrt(
236  square(edgeLength) - square(
237  baseRadius * cos(M_PI / numBaseEdges) -
238  minorRadius * cos(M_PI / edges2)));
239  double height = verts[base].z + (isUpwards ? h : -h);
240  angleShift += M_PI / edges2 +
241  (isRotated ? -M_PI / numBaseEdges : M_PI / numBaseEdges);
242  size_t minorBase = verts.size();
243  for (size_t i = 0; i < edges2; i++)
244  {
245  double ang = angleShift + 2 * M_PI * i / edges2;
246  verts.push_back(
247  TPoint3D(minorRadius * cos(ang), minorRadius * sin(ang), height));
248  }
249  CPolyhedron::TPolyhedronFace tri, quad, cBase;
250  tri.vertices.resize(3);
251  quad.vertices.resize(4);
252  cBase.vertices.resize(edges2);
253  size_t iq = isRotated ? 1 : 2, it = 0;
254  for (size_t i = 0; i < edges2; i++)
255  {
256  cBase.vertices[i] = it + minorBase;
257  size_t iiq = (iq + 1) % numBaseEdges + base;
258  size_t iiiq = (iiq + 1) % numBaseEdges + base;
259  size_t iit = (it + 1) % edges2 + minorBase;
260  quad.vertices[0] = it + minorBase;
261  quad.vertices[1] = iit;
262  quad.vertices[2] = iiq;
263  quad.vertices[3] = iq + base;
264  tri.vertices[0] = iit;
265  tri.vertices[1] = iiq;
266  tri.vertices[2] = iiiq;
267  iq = (iq + 2) % numBaseEdges;
268  it = (it + 1) % edges2;
269  faces.push_back(tri);
270  faces.push_back(quad);
271  }
272  if (edges2 >= 3) faces.push_back(cBase);
273 }
275  double angleShift, double baseRadius, bool isRotated, bool isUpwards,
276  size_t base, vector<TPoint3D>& verts,
277  vector<CPolyhedron::TPolyhedronFace>& faces)
278 {
279  double R1 = baseRadius * sqrt((5.0 - sqrt(5.0)) / 10.0);
280  double R2 = baseRadius * sqrt((5.0 + sqrt(5.0)) / 10.0);
281  double baseHeight = verts[base].z;
282  TPoint3D p1[5], p2[5];
283  angleShift += M_PI / 10;
284  if (isRotated) angleShift += M_PI / 5;
285  for (size_t i = 0; i < 5; i++)
286  {
287  double a = (i + i + 1) * M_PI / 5 + angleShift;
288  double b = (i + i) * M_PI / 5 + angleShift;
289  double ca = cos(a), sa = sin(a), cb = cos(b), sb = sin(b);
290  p1[i].x = R1 * ca;
291  p1[i].y = R1 * sa;
292  p1[i].z = baseHeight + (isUpwards ? R2 : -R2);
293  p2[i].x = R2 * cb;
294  p2[i].y = R2 * sb;
295  p2[i].z = baseHeight + (isUpwards ? R1 : -R1);
296  }
297  size_t newBase = verts.size();
298  for (size_t i = 0; i < 5; i++) verts.push_back(p1[i]);
299  for (size_t i = 0; i < 5; i++) verts.push_back(p2[i]);
301  f.vertices.resize(3);
302  g.vertices.resize(5);
303  size_t baseStart = isRotated ? 2 : 1;
304  for (size_t i = 0; i < 5; i++)
305  {
306  size_t ii = (i + 1) % 5;
307  f.vertices[0] = newBase + i;
308  f.vertices[1] = newBase + ii;
309  f.vertices[2] = newBase + ii + 5;
310  faces.push_back(f);
311  f.vertices[0] = newBase + i + 5;
312  f.vertices[1] = ((i + i + baseStart) % 10) + base;
313  f.vertices[2] = ((i + i + 9 + baseStart) % 10) + base;
314  faces.push_back(f);
315  g.vertices[0] = newBase + (ii % 5) + 5;
316  g.vertices[1] = newBase + i;
317  g.vertices[2] = newBase + i + 5;
318  g.vertices[3] = (i + i + baseStart) % 10 + base;
319  g.vertices[4] = (i + i + baseStart + 1) % 10 + base;
320  faces.push_back(g);
321  }
322  for (size_t i = 0; i < 5; i++) g.vertices[i] = i + newBase;
323  faces.push_back(g);
324  return;
325 }
326 inline size_t additionalFaces(JohnsonBodyPart j, uint32_t numBaseEdges)
327 {
328  if (j == INF_NO_BODY || j == SUP_NO_BODY)
329  return 1; // j is a base
330  else if (j < UPWARDS_CUPOLA)
331  return numBaseEdges; // j is a pyramid
332  else if (j < PRISM)
333  return numBaseEdges + ((numBaseEdges >= 6) ? 1 : 0); // j is a cupola
334  else if (j == PRISM)
335  return numBaseEdges;
336  else if (j == ANTIPRISM)
337  return numBaseEdges << 1;
338  else
339  return 16; // j is a rotunda
340 }
341 
342 inline bool faceContainsEdge(
345 {
346  char hm = 0;
347  for (vector<uint32_t>::const_iterator it = f.vertices.begin();
348  it != f.vertices.end(); ++it)
349  if (*it == e.v1 || *it == e.v2) hm++;
350  return hm == 2;
351 }
352 
353 bool getPlanesIntersection(const vector<const TPlane*>& planes, TPoint3D& pnt)
354 {
355  if (planes.size() < 3) return false;
356  char o = 0;
357  TPlane pl = *planes[0];
358  TLine3D l;
359  TObject3D obj;
360  for (size_t i = 1; i < planes.size(); i++) switch (o)
361  {
362  case 0:
363  if (!intersect(pl, *planes[i], obj)) return false;
364  if (obj.getPlane(pl))
365  o = 0;
366  else if (obj.getLine(l))
367  o = 1;
368  else if (obj.getPoint(pnt))
369  o = 2;
370  else
371  return false;
372  break;
373  case 1:
374  if (!intersect(l, *planes[i], obj)) return false;
375  if (obj.getLine(l))
376  o = 1;
377  else if (obj.getPoint(pnt))
378  o = 2;
379  else
380  return false;
381  break;
382  case 2:
383  if (!planes[i]->contains(pnt)) return false;
384  break;
385  default:
386  return false;
387  }
388  return o == 2;
389 }
390 
392  const vector<CPolyhedron::TPolyhedronFace>& fs, uint32_t v1, uint32_t v2,
393  uint32_t v3)
394 {
396  it != fs.end(); ++it)
397  {
398  const vector<uint32_t>& f = it->vertices;
399  size_t hmf = 0;
400  for (vector<uint32_t>::const_iterator it2 = f.begin(); it2 != f.end();
401  ++it2)
402  {
403  if (*it2 == v1)
404  hmf |= 1;
405  else if (*it2 == v2)
406  hmf |= 2;
407  else if (*it2 == v3)
408  hmf |= 4;
409  }
410  if (hmf == 7) return true;
411  }
412  return false;
413 }
415  const vector<CPolyhedron::TPolyhedronEdge>& es, uint32_t v1, uint32_t v2,
416  size_t& where)
417 {
418  for (where = 0; where < es.size(); where++)
419  {
420  const CPolyhedron::TPolyhedronEdge& e = es[where];
421  if (e.v1 == v1 && e.v2 == v2)
422  return true;
423  else if (e.v1 == v2 && e.v2 == v1)
424  return false;
425  }
426  throw std::logic_error("Internal error. Edge not found");
427 }
432 {
434  it != end; ++it)
435  {
436  const vector<uint32_t>& f = it->vertices;
437  char res = 0;
438  for (vector<uint32_t>::const_iterator it2 = f.begin(); it2 != f.end();
439  ++it2)
440  if (*it2 == v1)
441  res |= 1;
442  else if (*it2 == v2)
443  res |= 2;
444  if (res == 3) return true;
445  }
446  return false;
447 }
448 double getHeight(const TPolygon3D& p, const TPoint3D& c)
449 {
450  size_t N = p.size();
451  if (N > 5 || N < 3)
452  throw std::logic_error("Faces must have exactly 3, 4 or 5 vertices.");
453  double r = mrpt::math::distance(p[0], c);
454  double l = mrpt::math::distance(p[0], p[1]);
455  for (size_t i = 1; i < N; i++)
456  if (abs(mrpt::math::distance(p[i], c) - r) >=
458  throw std::logic_error("There is a non-regular polygon.");
459  else if (
460  abs(mrpt::math::distance(p[i], p[(i + 1) % N]) - l) >=
462  throw std::logic_error("There is a non-regular polygon.");
463  return sqrt(square(l) - square(r));
464 }
466 {
467  double d[3];
468  double mod;
469  inline double& operator[](size_t i) { return d[i]; }
470  inline double operator[](size_t i) const { return d[i]; }
471 };
472 // End of auxiliary data and code
473 
475  const vector<TPoint3D>& vertices) const
476 {
477  return mrpt::math::distance(vertices[v1], vertices[v2]);
478 }
479 
480 double CPolyhedron::TPolyhedronFace::area(const vector<TPoint3D>& vs) const
481 {
482  // Calculate as fan of triangles.
483  size_t N = vertices.size();
484  vector<SegmentVector> d(N - 1);
485  for (size_t i = 1; i < N; i++)
486  {
487  d[i - 1].mod = 0;
488  for (size_t j = 0; j < 3; j++)
489  {
490  d[i - 1][j] = vs[vertices[i]][j] - vs[vertices[0]][j];
491  d[i - 1].mod += square(d[i - 1][j]);
492  }
493  d[i - 1].mod = sqrt(d[i - 1].mod);
494  }
495  double res = 0;
496  for (size_t i = 1; i < N - 1; i++)
497  res += sqrt(
498  square(d[i - 1].mod * d[i].mod) -
499  square(dotProduct<3, double>(d[i - 1], d[i])));
500  return res / 2;
501 }
502 
503 void CPolyhedron::TPolyhedronFace::getCenter(
504  const vector<TPoint3D>& vrts, TPoint3D& p) const
505 {
506  p.x = p.y = p.z = 0.0;
507  for (vector<uint32_t>::const_iterator it = vertices.begin();
508  it != vertices.end(); ++it)
509  {
510  p.x += vrts[*it].x;
511  p.y += vrts[*it].y;
512  p.z += vrts[*it].z;
513  }
514  size_t N = vertices.size();
515  p.x /= N;
516  p.y /= N;
517  p.z /= N;
518 }
519 
520 CPolyhedron::CPolyhedron(const std::vector<math::TPolygon3D>& polys)
521  : mEdges(), mWireframe(false), mLineWidth(1), polygonsUpToDate(false)
522 {
523  std::vector<TPoint3D> vertices(0);
524  std::vector<TPolyhedronFace> faces;
525  if (!getVerticesAndFaces(polys, vertices, faces))
526  throw std::logic_error("Can't create CPolygon");
527  mVertices = std::move(vertices);
528  mFaces = std::move(faces);
529 
530  InitFromVertAndFaces(vertices, faces);
531 }
532 
534  const vector<TPoint3D>& vertices, const vector<vector<uint32_t>>& faces)
535 {
536  vector<TPolyhedronFace> aux;
537  for (vector<vector<uint32_t>>::const_iterator it = faces.begin();
538  it != faces.end(); ++it)
539  {
540  TPolyhedronFace f;
541  f.vertices = *it;
542  aux.push_back(f);
543  }
544  InitFromVertAndFaces(vertices, aux);
545 }
546 
548  double x1, double x2, double y1, double y2, double z1, double z2)
549 {
550  vector<TPoint3D> verts;
551  vector<TPolyhedronFace> faces;
552  for (int i = 0; i < 8; i++)
553  verts.push_back(
554  TPoint3D((i & 1) ? x2 : x1, (i & 2) ? y2 : y1, (i & 4) ? z2 : z1));
555  static uint32_t faceVertices[] = {0, 1, 5, 4, 2, 3, 7, 6, 0, 2, 6, 4,
556  1, 3, 7, 5, 0, 1, 3, 2, 4, 5, 7, 6};
557  TPolyhedronFace f;
558  for (uint32_t* p = reinterpret_cast<uint32_t*>(&faceVertices);
559  p < 24 + reinterpret_cast<uint32_t*>(&faceVertices); p += 4)
560  {
561  f.vertices.insert(f.vertices.begin(), p, p + 4);
562  faces.push_back(f);
563  f.vertices.clear();
564  }
565  return CreateNoCheck(verts, faces);
566 }
567 
569  const vector<TPoint2D>& baseVertices, double height)
570 {
571  uint32_t n = baseVertices.size();
572  if (baseVertices.size() < 3) throw std::logic_error("Not enought vertices");
573  vector<TPoint3D> verts;
574  vector<TPolyhedronFace> faces;
575  verts.push_back(TPoint3D(0, 0, height));
576  for (vector<TPoint2D>::const_iterator it = baseVertices.begin();
577  it != baseVertices.end(); ++it)
578  verts.push_back(TPoint3D(it->x, it->y, 0));
579  TPolyhedronFace f, g;
580  f.vertices.push_back(0);
581  f.vertices.push_back(n);
582  f.vertices.push_back(1);
583  g.vertices.push_back(1);
584  faces.push_back(f);
585  for (uint32_t i = 2; i <= n; i++)
586  {
587  f.vertices.erase(f.vertices.begin() + 1);
588  f.vertices.push_back(i);
589  faces.push_back(f);
590  g.vertices.push_back(i);
591  }
592  faces.push_back(g);
593  return CreateNoCheck(verts, faces);
594 }
595 
597  const vector<TPoint2D>& baseVertices, double height1, double height2)
598 {
599  uint32_t N = baseVertices.size();
600  if (N < 3) throw std::logic_error("Not enought vertices");
601  vector<TPoint3D> verts;
602  verts.reserve(N + 2);
603  vector<TPolyhedronFace> faces;
604  faces.reserve(N << 1);
605  verts.push_back(TPoint3D(0, 0, height1));
606  for (vector<TPoint2D>::const_iterator it = baseVertices.begin();
607  it != baseVertices.end(); ++it)
608  verts.push_back(TPoint3D(it->x, it->y, 0));
609  verts.push_back(TPoint3D(0, 0, -height2));
610  TPolyhedronFace f, g;
611  f.vertices.resize(3);
612  g.vertices.resize(3);
613  f.vertices[0] = 0;
614  g.vertices[0] = N + 1;
615  for (uint32_t i = 1; i < N; i++)
616  {
617  f.vertices[1] = g.vertices[1] = i;
618  f.vertices[2] = g.vertices[2] = i + 1;
619  faces.push_back(f);
620  faces.push_back(g);
621  }
622  f.vertices[1] = g.vertices[1] = 1;
623  faces.push_back(f);
624  faces.push_back(g);
625  return CreateNoCheck(verts, faces);
626 }
627 
629  const vector<TPoint2D>& baseVertices, double height, double ratio)
630 {
631  uint32_t n = baseVertices.size();
632  if (n < 3) throw std::logic_error("Not enough vertices");
633  vector<TPoint3D> verts(n + n);
634  vector<TPolyhedronFace> faces(n + 2);
635  TPolyhedronFace f, g, h;
636  f.vertices.resize(4);
637  g.vertices.resize(n);
638  h.vertices.resize(n);
639  for (uint32_t i = 0; i < n; i++)
640  {
641  verts[i] = TPoint3D(baseVertices[i].x, baseVertices[i].y, 0);
642  verts[i + n] = TPoint3D(
643  baseVertices[i].x * ratio, baseVertices[i].y * ratio, height);
644  uint32_t ii = (i + 1) % n;
645  f.vertices[0] = i;
646  f.vertices[1] = ii;
647  f.vertices[2] = ii + n;
648  f.vertices[3] = i + n;
649  faces[i] = f;
650  g.vertices[i] = i;
651  h.vertices[i] = i + n;
652  }
653  faces[n] = g;
654  faces[n + 1] = h;
655  return CreateNoCheck(verts, faces);
656 }
657 
659  const vector<TPoint2D>& bottomBase, const vector<TPoint2D>& topBase,
660  const double height)
661 {
662  uint32_t n = bottomBase.size();
663  if (n < 3) throw std::logic_error("Not enough vertices");
664  if (n != topBase.size())
665  throw std::logic_error("Bases' number of vertices do not match");
666  vector<TPoint3D> verts(n + n);
667  vector<TPolyhedronFace> faces(n + n + 2);
668  TPolyhedronFace f, g, h;
669  f.vertices.resize(3);
670  g.vertices.resize(n);
671  h.vertices.resize(n);
672  for (uint32_t i = 0; i < n; i++)
673  {
674  verts[i] = TPoint3D(bottomBase[i].x, bottomBase[i].y, 0);
675  verts[n + i] = TPoint3D(topBase[i].x, topBase[i].y, height);
676  uint32_t ii = (i + 1) % n;
677  f.vertices[0] = i;
678  f.vertices[1] = ii;
679  f.vertices[2] = i + n;
680  faces[i] = f;
681  f.vertices[0] = i + n;
682  f.vertices[1] = ii + n;
683  f.vertices[2] = ii;
684  faces[n + i] = f;
685  g.vertices[i] = i;
686  h.vertices[i] = n + i;
687  }
688  faces[n + n] = g;
689  faces[n + n + 1] = h;
690  return CreateNoCheck(verts, faces);
691 }
692 
694  const TPoint3D& base, const TPoint3D& v1, const TPoint3D& v2,
695  const TPoint3D& v3)
696 {
697  vector<TPoint3D> verts(8);
698  vector<TPolyhedronFace> faces(6);
699  for (uint32_t i = 0; i < 8; i++)
700  {
701  verts[i] = base;
702  if (i & 1) verts[i] = verts[i] + v1;
703  if (i & 2) verts[i] = verts[i] + v2;
704  if (i & 4) verts[i] = verts[i] + v3;
705  }
706  TPolyhedronFace f;
707  f.vertices.resize(4);
708  f.vertices[0] = 0;
709  f.vertices[1] = 1;
710  f.vertices[2] = 3;
711  f.vertices[3] = 2;
712  faces[0] = f;
713  // f.vertices[0]=0;
714  // f.vertices[1]=1;
715  f.vertices[2] = 5;
716  f.vertices[3] = 4;
717  faces[1] = f;
718  // f.vertices[0]=0;
719  f.vertices[1] = 2;
720  f.vertices[2] = 6;
721  // f.vertices[3]=4;
722  faces[2] = f;
723  for (uint32_t i = 0; i < 3; i++)
724  {
725  uint32_t valueAdd = 4 >> i;
726  faces[i + 3].vertices.resize(4);
727  for (uint32_t j = 0; j < 4; j++)
728  faces[i + 3].vertices[j] = faces[i].vertices[j] + valueAdd;
729  }
730  return CreateNoCheck(verts, faces);
731 }
732 
734  const vector<TPoint2D>& baseVertices, double height1, double ratio1,
735  double height2, double ratio2)
736 {
737  // TODO: check special case in which ratio=0.
738  size_t N = baseVertices.size();
739  vector<TPoint3D> verts(3 * N);
740  size_t N2 = N + N;
741  for (size_t i = 0; i < N; i++)
742  {
743  double x = baseVertices[i].x;
744  double y = baseVertices[i].y;
745  verts[i].x = x;
746  verts[i].y = y;
747  verts[i].z = 0;
748  verts[i + N].x = x * ratio1;
749  verts[i + N].y = y * ratio1;
750  verts[i + N].z = height1;
751  verts[i + N2].x = x * ratio2;
752  verts[i + N2].y = y * ratio2;
753  verts[i + N2].z = -height2; // This is not an error. This way, two
754  // positive heights produce an actual
755  // bifrustum.
756  }
757  vector<TPolyhedronFace> faces(N2 + 2);
758  TPolyhedronFace f, g, h;
759  f.vertices.resize(4);
760  g.vertices.resize(N);
761  h.vertices.resize(N);
762  for (size_t i = 0; i < N; i++)
763  {
764  size_t i2 = (i + 1) % N;
765  f.vertices[0] = i;
766  f.vertices[1] = i2;
767  f.vertices[2] = i2 + N;
768  f.vertices[3] = i + N;
769  faces[i] = f;
770  f.vertices[2] = i2 + N2;
771  f.vertices[3] = i + N2;
772  faces[i + N] = f;
773  g.vertices[i] = i + N;
774  h.vertices[i] = i + N2;
775  }
776  faces[N2] = g;
777  faces[N2 + 1] = h;
778  return CreateNoCheck(verts, faces);
779 }
780 
782  uint32_t numBaseEdges, double baseRadius, double basesDistance)
783 {
784  if (numBaseEdges < 3) throw std::logic_error("Not enough vertices");
785  if (basesDistance == 0 || baseRadius == 0) return CreateEmpty();
786  size_t numBaseEdges2 = numBaseEdges << 1;
787  vector<TPoint3D> verts(numBaseEdges2 + 2);
788  double space = 2 * M_PI / numBaseEdges;
789  double shift = space / 2;
790  double height1 = basesDistance / 2;
791  double cospii = cos(M_PI / numBaseEdges);
792  double height2 =
793  height1 * (cospii + 1) /
794  (1 - cospii); // Apex height, calculated so each face conforms a plane
795  for (size_t i = 0; i < numBaseEdges; i++)
796  {
797  double ang = space * i;
798  double ang2 = ang + shift;
799  size_t ii = i + numBaseEdges;
800  verts[i].x = baseRadius * cos(ang);
801  verts[i].y = baseRadius * sin(ang);
802  verts[i].z = -height1;
803  verts[ii].x = baseRadius * cos(ang2);
804  verts[ii].y = baseRadius * sin(ang2);
805  verts[ii].z = height1;
806  }
807  verts[numBaseEdges2].x = 0;
808  verts[numBaseEdges2].y = 0;
809  verts[numBaseEdges2].z = -height2;
810  verts[numBaseEdges2 + 1].x = 0;
811  verts[numBaseEdges2 + 1].y = 0;
812  verts[numBaseEdges2 + 1].z = height2;
813  vector<TPolyhedronFace> faces(numBaseEdges2);
814  TPolyhedronFace f, g;
815  f.vertices.resize(4);
816  g.vertices.resize(4);
817  f.vertices[3] = numBaseEdges2;
818  g.vertices[3] = numBaseEdges2 + 1;
819  for (size_t i = 0; i < numBaseEdges; i++)
820  {
821  size_t ii = (i + 1) % numBaseEdges;
822  size_t i2 = i + numBaseEdges;
823  f.vertices[0] = i;
824  f.vertices[1] = i2;
825  f.vertices[2] = ii;
826  g.vertices[0] = i2;
827  g.vertices[1] = ii;
828  g.vertices[2] = ii + numBaseEdges;
829  faces[i] = f;
830  faces[i + numBaseEdges] = g;
831  }
832  return CreateNoCheck(verts, faces);
833 }
834 
836  uint32_t numBaseEdges, double baseRadius, const std::string& components,
837  size_t shifts)
838 {
839  if (baseRadius == 0) return CreateEmpty();
840  if (numBaseEdges < 3) throw std::logic_error("Not enough vertices");
841  vector<JohnsonBodyPart> parts;
842  if (!analyzeJohnsonPartsString(components, numBaseEdges, parts))
843  throw std::logic_error("Invalid string");
844  // Some common values are computed
845  size_t nParts = parts.size();
846  double edgeLength = 2 * baseRadius * sin(M_PI / numBaseEdges);
847  double antiPrismHeight = sqrt(
848  square(edgeLength) -
849  square(baseRadius) * (2 - 2 * cos(M_PI / numBaseEdges)));
850  // Vertices' and faces' vectors are computed
851  size_t nVerts = numBaseEdges * (nParts - 1) +
852  additionalVertices(parts[0], numBaseEdges) +
853  additionalVertices(*parts.rbegin(), numBaseEdges);
854  size_t nFaces = 0;
855  for (size_t i = 0; i < nParts; i++)
856  nFaces += additionalFaces(parts[i], numBaseEdges);
857  vector<TPoint3D> verts;
858  verts.reserve(nVerts);
859  vector<TPolyhedronFace> faces;
860  faces.reserve(nFaces);
861  // Each base's position is computed. Also, the height is set so that the
862  // polyhedron is vertically centered in z=0.
863  double h, mHeight = 0;
864  vector<pair<double, size_t>> basePositionInfo(nParts - 1);
865  for (size_t i = 0; i < nParts - 1; i++)
866  {
867  if (parts[i] == PRISM)
868  h = edgeLength;
869  else if (parts[i] == ANTIPRISM)
870  {
871  h = antiPrismHeight;
872  shifts++;
873  }
874  else
875  h = 0;
876  basePositionInfo[i] = make_pair(mHeight += h, shifts);
877  }
878  mHeight /= 2;
879  double semi = M_PI / numBaseEdges;
880  // All the bases are generated and inserted into the vertices' vector.
881  for (vector<pair<double, size_t>>::const_iterator it =
882  basePositionInfo.begin();
883  it != basePositionInfo.end(); ++it)
885  numBaseEdges, baseRadius, it->first - mHeight, semi * it->second,
886  verts);
887  size_t initialBase = 0, endBase = 0;
889  face.vertices.reserve(numBaseEdges);
890  // Each body is inserted.
891  for (size_t i = 0; i < nParts; i++)
892  {
893  switch (parts[i])
894  {
895  case INF_NO_BODY:
896  // Inferior base.
897  face.vertices.resize(numBaseEdges);
898  for (size_t i = 0; i < numBaseEdges; i++)
899  face.vertices[i] = endBase + i;
900  faces.push_back(face);
901  break;
902  case SUP_NO_BODY:
903  // Superior base.
904  face.vertices.resize(numBaseEdges);
905  for (size_t i = 0; i < numBaseEdges; i++)
906  face.vertices[i] = initialBase + i;
907  faces.push_back(face);
908  break;
909  case UPWARDS_PYRAMID:
910  {
911  // Upwards-pointing pyramid. There must be 5 or less vertices.
912  double apexHeight =
913  baseRadius * sqrt(4 * square(sin(M_PI / numBaseEdges)) - 1);
914  face.vertices.resize(3);
915  face.vertices[0] = verts.size();
916  face.vertices[1] = initialBase + numBaseEdges - 1;
917  face.vertices[2] = initialBase;
918  do
919  {
920  faces.push_back(face);
921  face.vertices[1] = face.vertices[2];
922  face.vertices[2]++;
923  } while (face.vertices[2] < initialBase + numBaseEdges);
924  verts.push_back(
925  TPoint3D(0, 0, verts[initialBase].z + apexHeight));
926  break;
927  }
928  case DOWNWARDS_PYRAMID:
929  {
930  // Downwards-pointing pyramid. There must be 5 or less vertices.
931  double apexHeight =
932  baseRadius * sqrt(4 * square(sin(M_PI / numBaseEdges)) - 1);
933  face.vertices.resize(3);
934  face.vertices[0] = verts.size();
935  face.vertices[1] = endBase + numBaseEdges - 1;
936  face.vertices[2] = endBase;
937  do
938  {
939  faces.push_back(face);
940  face.vertices[1] = face.vertices[2];
941  face.vertices[2]++;
942  } while (face.vertices[2] < endBase + numBaseEdges);
943  verts.push_back(TPoint3D(0, 0, verts[endBase].z - apexHeight));
944  break;
945  }
946  case UPWARDS_CUPOLA:
947  // Upwards-pointing cupola. There must be an even amount of
948  // vertices.
949  insertCupola(
950  numBaseEdges, basePositionInfo.rbegin()->second * semi,
951  baseRadius, edgeLength, false, true, initialBase, verts,
952  faces);
953  break;
954  case DOWNWARDS_CUPOLA:
955  // Downwards-pointing cupola. There must be an even amount of
956  // vertices.
957  insertCupola(
958  numBaseEdges, basePositionInfo[0].second * semi, baseRadius,
959  edgeLength, false, false, endBase, verts, faces);
960  break;
962  // Upwards-pointing, slightly rotated, cupola. There must be an
963  // even amount of vertices.
964  insertCupola(
965  numBaseEdges, basePositionInfo.rbegin()->second * semi,
966  baseRadius, edgeLength, true, true, initialBase, verts,
967  faces);
968  break;
970  // Downwards-pointing, slightly rotated, cupola. There must be
971  // an even amount of vertices.
972  insertCupola(
973  numBaseEdges, basePositionInfo[0].second * semi, baseRadius,
974  edgeLength, true, false, endBase, verts, faces);
975  break;
976  case PRISM:
977  // Archimedean prism.
978  face.vertices.resize(4);
979  for (size_t i = 0; i < numBaseEdges; i++)
980  {
981  size_t ii = (i + 1) % numBaseEdges;
982  face.vertices[0] = initialBase + i;
983  face.vertices[1] = endBase + i;
984  face.vertices[2] = endBase + ii;
985  face.vertices[3] = initialBase + ii;
986  faces.push_back(face);
987  }
988  break;
989  case ANTIPRISM:
990  {
991  // Archimedean antiprism.
992  face.vertices.resize(3);
993  face.vertices[0] = initialBase;
994  face.vertices[1] = endBase;
995  face.vertices[2] = initialBase + 1;
996  bool nextIsEnd = true;
997  size_t nextEnd = 1;
998  size_t nextInitial = 2;
999  for (size_t i = 0; i < numBaseEdges << 1; i++)
1000  {
1001  faces.push_back(face);
1002  face.vertices[0] = face.vertices[1];
1003  face.vertices[1] = face.vertices[2];
1004  if (nextIsEnd)
1005  {
1006  face.vertices[2] = endBase + nextEnd;
1007  nextEnd = (nextEnd + 1) % numBaseEdges;
1008  }
1009  else
1010  {
1011  face.vertices[2] = initialBase + nextInitial;
1012  nextInitial = (nextInitial + 1) % numBaseEdges;
1013  }
1014  nextIsEnd = !nextIsEnd;
1015  }
1016  break;
1017  }
1018  case UPWARDS_ROTUNDA:
1019  // Upwards-pointing pentagonal rotunda. Only for bases of
1020  // exactly 10 vertices.
1021  insertRotunda(
1022  basePositionInfo.rbegin()->second * semi, baseRadius, false,
1023  true, initialBase, verts, faces);
1024  break;
1025  case DOWNWARDS_ROTUNDA:
1026  // Downwards-pointing pentagonal rotunda. Only for bases of
1027  // exactly 10 vertices.
1028  insertRotunda(
1029  basePositionInfo[0].second * semi, baseRadius, false, false,
1030  endBase, verts, faces);
1031  break;
1033  // Upwards-pointing, slightly rotated, pentagonal rotunda. Only
1034  // for bases of exactly 10 vertices.
1035  insertRotunda(
1036  basePositionInfo.rbegin()->second * semi, baseRadius, true,
1037  true, initialBase, verts, faces);
1038  break;
1040  // Downwards-pointing, slightly rotated, pentagonal rotunda.
1041  // Only for bases of exactly 10 vertices.
1042  insertRotunda(
1043  basePositionInfo[0].second * semi, baseRadius, true, false,
1044  endBase, verts, faces);
1045  break;
1046  default:
1047  throw std::logic_error("Internal error");
1048  }
1049  initialBase = endBase;
1050  endBase += numBaseEdges;
1051  }
1052  return CreateNoCheck(verts, faces);
1053 }
1054 
1055 /*---------------------------------------------------------------
1056  render
1057  ---------------------------------------------------------------*/
1058 
1060 {
1061 #if MRPT_HAS_OPENGL_GLUT
1062  if (mWireframe)
1063  {
1064  glDisable(GL_LIGHTING); // Disable lights when drawing lines
1065 
1067  checkOpenGLError();
1069  glBegin(GL_LINES);
1071  it != mEdges.end(); ++it)
1072  {
1073  TPoint3D p = mVertices[it->v1];
1074  glVertex3f(p.x, p.y, p.z);
1075  p = mVertices[it->v2];
1076  glVertex3f(p.x, p.y, p.z);
1077  }
1078  glEnd();
1079  glEnable(GL_LIGHTING); // Disable lights when drawing lines
1080  }
1081  else
1082  {
1083  checkOpenGLError();
1084  glEnable(GL_BLEND);
1086 
1089  it != mFaces.end(); ++it)
1090  {
1092  glNormal3f(it->normal[0], it->normal[1], it->normal[2]);
1093  for (vector<uint32_t>::const_iterator it2 = it->vertices.begin();
1094  it2 != it->vertices.end(); ++it2)
1095  {
1096  const TPoint3D& p = mVertices[*it2];
1097  glVertex3f(p.x, p.y, p.z);
1098  }
1099  glEnd();
1100  }
1102  }
1103 #endif
1104 }
1105 
1106 bool CPolyhedron::traceRay(const mrpt::poses::CPose3D& o, double& dist) const
1107 {
1109  return math::traceRay(tempPolygons, o - this->m_pose, dist);
1110 }
1111 
1112 void CPolyhedron::getEdgesLength(std::vector<double>& lengths) const
1113 {
1114  lengths.resize(mEdges.size());
1115  std::vector<double>::iterator it2 = lengths.begin();
1117  it != mEdges.end(); ++it, ++it2)
1118  *it2 = it->length(mVertices);
1119 }
1120 
1121 void CPolyhedron::getFacesArea(std::vector<double>& areas) const
1122 {
1123  areas.resize(mFaces.size());
1124  std::vector<double>::iterator it2 = areas.begin();
1126  it != mFaces.end(); ++it, ++it2)
1127  *it2 = it->area(mVertices);
1128 }
1129 
1131 {
1132  // TODO. Calculate as set of pyramids whose apices are situated in the
1133  // center of the polyhedron (will work only with convex polyhedrons).
1134  // Pyramid volume=V=1/3*base area*height. Height=abs((A-V)·N), where A is
1135  // the apex, V is any other vertex, N is the base's normal vector and (·) is
1136  // the scalar product.
1137  TPoint3D center;
1138  getCenter(center);
1139  double res = 0;
1142  vector<double> areas(mFaces.size());
1143  getFacesArea(areas);
1144  vector<double>::const_iterator itA = areas.begin();
1146  it != mFaces.end(); ++it, ++itP, ++itA)
1147  res += abs(itP->plane.distance(center)) * (*itA);
1148  return res / 3;
1149 }
1150 
1151 void CPolyhedron::getSetOfPolygons(std::vector<math::TPolygon3D>& vec) const
1152 {
1154  size_t N = tempPolygons.size();
1155  vec.resize(N);
1156  for (size_t i = 0; i < N; i++) vec[i] = tempPolygons[i].poly;
1157 }
1158 
1160  std::vector<math::TPolygon3D>& vec) const
1161 {
1162  vec.resize(mFaces.size());
1163  size_t N = mVertices.size();
1164  vector<TPoint3D> nVerts;
1165  nVerts.resize(N);
1166  CPose3D pose = this->m_pose;
1167  for (size_t i = 0; i < N; i++) pose.composePoint(mVertices[i], nVerts[i]);
1168  transform(
1169  mFaces.begin(), mFaces.end(), vec.begin(),
1171 }
1172 
1174 {
1175  vector<TPolygon3D> polys, polysTMP, polys2;
1176  getSetOfPolygons(polys);
1177  polys2.reserve(polys.size());
1178  for (vector<TPolygon3D>::const_iterator it = polys.begin();
1179  it != polys.end(); ++it)
1180  if (mrpt::math::splitInConvexComponents(*it, polysTMP))
1181  polys2.insert(polys2.end(), polysTMP.begin(), polysTMP.end());
1182  else
1183  polys2.push_back(*it);
1184  mVertices.clear();
1185  mEdges.clear();
1186  mFaces.clear();
1188  for (vector<TPolyhedronFace>::iterator it = mFaces.begin();
1189  it != mFaces.end(); ++it)
1190  {
1191  if (!setNormal(*it, false))
1192  throw std::logic_error("Bad face specification");
1193  addEdges(*it);
1194  }
1195 }
1196 
1198 {
1199  size_t N = mVertices.size();
1200  if (N == 0) throw new std::logic_error("There are no vertices");
1201  center.x = center.y = center.z = 0;
1202  for (vector<TPoint3D>::const_iterator it = mVertices.begin();
1203  it != mVertices.end(); ++it)
1204  {
1205  center.x += it->x;
1206  center.y += it->y;
1207  center.z += it->z;
1208  }
1209  center.x /= N;
1210  center.y /= N;
1211  center.z /= N;
1212 }
1213 
1215 {
1216  switch (mrpt::random::getRandomGenerator().drawUniform32bit() % 34)
1217  {
1218  case 0:
1219  return CreateTetrahedron(radius);
1220  case 1:
1221  return CreateHexahedron(radius);
1222  case 2:
1223  return CreateOctahedron(radius);
1224  case 3:
1225  return CreateDodecahedron(radius);
1226  case 4:
1227  return CreateIcosahedron(radius);
1228  case 5:
1229  return CreateTruncatedTetrahedron(radius);
1230  case 6:
1231  return CreateTruncatedHexahedron(radius);
1232  case 7:
1233  return CreateTruncatedOctahedron(radius);
1234  case 8:
1235  return CreateTruncatedDodecahedron(radius);
1236  case 9:
1237  return CreateTruncatedIcosahedron(radius);
1238  case 10:
1239  return CreateCuboctahedron(radius);
1240  case 11:
1241  return CreateRhombicuboctahedron(radius);
1242  case 12:
1243  return CreateIcosidodecahedron(radius);
1244  case 13:
1245  return CreateRhombicosidodecahedron(radius);
1246  case 14:
1247  return CreateTriakisTetrahedron(radius);
1248  case 15:
1249  return CreateTriakisOctahedron(radius);
1250  case 16:
1251  return CreateTetrakisHexahedron(radius);
1252  case 17:
1253  return CreateTriakisIcosahedron(radius);
1254  case 18:
1255  return CreatePentakisDodecahedron(radius);
1256  case 19:
1257  return CreateRhombicDodecahedron(radius);
1258  case 20:
1259  return CreateDeltoidalIcositetrahedron(radius);
1260  case 21:
1261  return CreateRhombicTriacontahedron(radius);
1262  case 22:
1263  return CreateDeltoidalHexecontahedron(radius);
1264  case 23:
1266  (mrpt::random::getRandomGenerator().drawUniform32bit() % 10) + 3,
1267  radius);
1268  case 24:
1270  (mrpt::random::getRandomGenerator().drawUniform32bit() % 10) + 3,
1271  radius);
1272  case 25:
1274  ((mrpt::random::getRandomGenerator().drawUniform32bit() % 4) << 1) +
1275  4,
1276  radius, "C+");
1277  case 26:
1279  ((mrpt::random::getRandomGenerator().drawUniform32bit() % 4) << 1) +
1280  4,
1281  radius, "C-C+");
1282  case 27:
1284  ((mrpt::random::getRandomGenerator().drawUniform32bit() % 4) << 1) +
1285  4,
1286  radius, "C-PRC+");
1287  case 28:
1289  ((mrpt::random::getRandomGenerator().drawUniform32bit() % 4) << 1) +
1290  4,
1291  radius, "C-AC+");
1292  case 29:
1293  return CreateJohnsonSolidWithConstantBase(10, radius, "R+");
1294  case 30:
1295  return CreateJohnsonSolidWithConstantBase(10, radius, "R-PRR+");
1296  case 31:
1297  return CreateJohnsonSolidWithConstantBase(10, radius, "R-AR+");
1298  case 32:
1300  (mrpt::random::getRandomGenerator().drawUniform32bit() % 5) + 3,
1301  radius);
1302  case 33:
1304  (mrpt::random::getRandomGenerator().drawUniform32bit() % 5) + 3,
1305  radius);
1306  default:
1307  return CreateEmpty();
1308  }
1309 }
1310 
1312 {
1313  // This methods builds the dual of a given polyhedron, which is assumed to
1314  // be centered in (0,0,0), using polar reciprocation.
1315  // A vertex (x0,y0,z0), which is inside a circunference x^2+y^2+z^2=r^2, its
1316  // dual face will lie on the x0·x+y0·y+z0·z=r^2 plane.
1317  // The new vertices can, then, be calculated as the corresponding
1318  // intersections between three or more planes.
1319  size_t NV = mFaces.size();
1320  size_t NE = mEdges.size();
1321  size_t NF = mVertices.size();
1322  vector<TPlane> planes(NF);
1323  for (size_t i = 0; i < NF; i++)
1324  {
1325  const TPoint3D& p = mVertices[i];
1326  TPlane& pl = planes[i];
1327  pl.coefs[0] = p.x;
1328  pl.coefs[1] = p.y;
1329  pl.coefs[2] = p.z;
1330  pl.coefs[3] = -square(p.x) - square(p.y) - square(p.z);
1331  }
1332  CMatrixTemplate<bool> incidence(NV, NF);
1333  vector<TPoint3D> vertices(NV);
1334  for (size_t i = 0; i < NV; i++)
1335  {
1336  for (size_t j = 0; j < NF; j++) incidence(i, j) = false;
1337  vector<const TPlane*> fPls;
1338  fPls.reserve(mFaces[i].vertices.size());
1339  for (vector<uint32_t>::const_iterator it = mFaces[i].vertices.begin();
1340  it != mFaces[i].vertices.end(); ++it)
1341  {
1342  incidence(i, *it) = true;
1343  fPls.push_back(&planes[*it]);
1344  }
1345  if (!getPlanesIntersection(fPls, vertices[i]))
1346  throw std::logic_error("Dual polyhedron cannot be found");
1347  }
1348  vector<TPolyhedronFace> faces(NF);
1349  for (size_t i = 0; i < NF; i++)
1350  for (size_t j = 0; j < NV; j++)
1351  if (incidence(j, i)) faces[i].vertices.push_back(j);
1352  // The following code ensures that the faces' vertex list is in the adequate
1353  // order.
1354  CMatrixTemplate<bool> arrayEF(NE, NV);
1355  for (size_t i = 0; i < NE; i++)
1356  for (size_t j = 0; j < NV; j++)
1357  arrayEF(i, j) = faceContainsEdge(mFaces[j], mEdges[i]);
1358  for (vector<TPolyhedronFace>::iterator it = faces.begin();
1359  it != faces.end(); ++it)
1360  {
1361  vector<uint32_t>& face = it->vertices;
1362  if (face.size() <= 3) continue;
1363  size_t index = 0;
1364  while (index < face.size() - 1)
1365  {
1366  bool err = true;
1367  while (err)
1368  {
1369  for (size_t i = 0; i < NE; i++)
1370  if (arrayEF(i, face[index]) && arrayEF(i, face[index + 1]))
1371  {
1372  err = false;
1373  break;
1374  }
1375  if (err)
1376  {
1377  size_t val = face[index + 1];
1378  face.erase(face.begin() + index + 1);
1379  face.push_back(val);
1380  }
1381  }
1382  index++;
1383  }
1384  }
1385  return mrpt::make_aligned_shared<CPolyhedron>(vertices, faces);
1386 }
1387 
1389 {
1390  if (factor < 0) return CreateEmpty();
1391  if (factor == 0)
1392  return CreateNoCheck(mVertices, mFaces);
1393  else if (factor < 1)
1394  {
1395  size_t NE = mEdges.size();
1396  size_t NV = mVertices.size();
1397  size_t NF = mFaces.size();
1398  vector<TPoint3D> vertices(NE << 1);
1399  vector<TPolyhedronFace> faces(NV + NF);
1400  for (size_t i = 0; i < NE; i++)
1401  {
1402  const TPoint3D& p1 = mVertices[mEdges[i].v1];
1403  const TPoint3D& p2 = mVertices[mEdges[i].v2];
1404  TPoint3D& v1 = vertices[i + i];
1405  TPoint3D& v2 = vertices[i + i + 1];
1406  for (size_t j = 0; j < 3; j++)
1407  {
1408  double d = (p2[j] - p1[j]) * factor / 2;
1409  v1[j] = p1[j] + d;
1410  v2[j] = p2[j] - d;
1411  }
1412  faces[mEdges[i].v1].vertices.push_back(i + i);
1413  faces[mEdges[i].v2].vertices.push_back(i + i + 1);
1414  }
1415  for (size_t i = 0; i < NV; i++)
1416  {
1417  vector<uint32_t>& f = faces[i].vertices;
1418  size_t sf = f.size();
1419  if (sf == 3) continue;
1420  for (size_t j = 1; j < sf - 1; j++)
1421  {
1422  const TPolyhedronEdge& e1 = mEdges[f[j - 1] / 2];
1423  for (;;)
1424  {
1425  const TPolyhedronEdge& e2 = mEdges[f[j] / 2];
1426  if (!((e1.v1 == i || e1.v2 == i) &&
1427  (e2.v1 == i || e2.v2 == i)))
1428  THROW_EXCEPTION("En algo te has equivocado, chaval.");
1429  if (searchForFace(
1430  mFaces, i, (e1.v1 == i) ? e1.v2 : e1.v1,
1431  (e2.v1 == i) ? e2.v2 : e2.v1))
1432  break;
1433  uint32_t tmpV = f[j];
1434  f.erase(f.begin() + j);
1435  f.push_back(tmpV);
1436  }
1437  }
1438  }
1439  for (size_t i = 0; i < NF; i++)
1440  {
1441  vector<uint32_t>& f = faces[i + NV].vertices;
1442  const vector<uint32_t>& cf = mFaces[i].vertices;
1443  size_t hmV = cf.size();
1444  f.reserve(hmV << 1);
1445  for (size_t j = 0; j < hmV; j++)
1446  {
1447  size_t where;
1448  if (searchForEdge(mEdges, cf[j], cf[(j + 1) % hmV], where))
1449  {
1450  f.push_back(where << 1);
1451  f.push_back((where << 1) + 1);
1452  }
1453  else
1454  {
1455  f.push_back((where << 1) + 1);
1456  f.push_back(where << 1);
1457  }
1458  }
1459  }
1460  return mrpt::make_aligned_shared<CPolyhedron>(vertices, faces);
1461  }
1462  else if (factor == 1)
1463  {
1464  size_t NE = mEdges.size();
1465  size_t NV = mVertices.size();
1466  size_t NF = mFaces.size();
1467  vector<TPoint3D> vertices(NE);
1468  vector<TPolyhedronFace> faces(NV + NF);
1469  for (size_t i = 0; i < NE; i++)
1470  {
1471  const TPoint3D& p1 = mVertices[mEdges[i].v1];
1472  const TPoint3D& p2 = mVertices[mEdges[i].v2];
1473  TPoint3D& dst = vertices[i];
1474  for (size_t j = 0; j < 3; j++) dst[j] = (p1[j] + p2[j]) / 2;
1475  faces[mEdges[i].v1].vertices.push_back(i);
1476  faces[mEdges[i].v2].vertices.push_back(i);
1477  }
1478  for (size_t i = 0; i < NV; i++)
1479  {
1480  vector<uint32_t>& f = faces[i].vertices;
1481  size_t sf = f.size();
1482  if (sf == 3) continue;
1483  for (size_t j = 1; j < sf - 1; j++)
1484  {
1485  const TPolyhedronEdge& e1 = mEdges[f[j - 1]];
1486  for (;;)
1487  {
1488  const TPolyhedronEdge& e2 = mEdges[f[j - 1]];
1489  if (!((e1.v1 == i || e1.v2 == i) &&
1490  (e2.v1 == 1 || e2.v2 == i)))
1491  THROW_EXCEPTION("En algo te has equivocado, chaval.");
1492  if (searchForFace(
1493  mFaces, i, (e1.v1 == i) ? e1.v2 : e1.v1,
1494  (e2.v1 == i) ? e2.v2 : e2.v1))
1495  break;
1496  uint32_t tmpV = f[j];
1497  f.erase(f.begin() + j);
1498  f.push_back(tmpV);
1499  }
1500  }
1501  }
1502  for (size_t i = 0; i < NF; i++)
1503  {
1504  vector<uint32_t>& f = faces[i + NV].vertices;
1505  const vector<uint32_t>& cf = mFaces[i].vertices;
1506  size_t hmV = cf.size();
1507  f.reserve(hmV);
1508  for (size_t j = 0; j < hmV; j++)
1509  {
1510  size_t where;
1511  searchForEdge(mEdges, cf[j], cf[(j + 1) % hmV], where);
1512  f.push_back(where);
1513  }
1514  }
1515  return mrpt::make_aligned_shared<CPolyhedron>(vertices, faces);
1516  }
1517  else
1518  return CreateEmpty();
1519 }
1520 
1522 {
1523  if (factor < 0)
1524  return CreateEmpty();
1525  else if (factor == 0)
1526  return CreateNoCheck(mVertices, mFaces);
1527  size_t NV = mVertices.size();
1528  size_t NE = mEdges.size();
1529  size_t NF = mFaces.size();
1530  vector<TPolygon3D> origFaces(NF);
1531  getSetOfPolygons(origFaces);
1532  TPoint3D cnt;
1533  getCenter(cnt);
1534  vector<TPoint3D> polyCenters(NF);
1535  vector<TPoint3D> polyNewCenters(NF);
1536  size_t NNV = 0;
1537  for (size_t i = 0; i < NF; i++)
1538  {
1539  origFaces[i].getCenter(polyCenters[i]);
1540  polyCenters[i] -= cnt;
1541  polyNewCenters[i] = polyCenters[i];
1542  polyNewCenters[i] *= (1 + factor);
1543  polyNewCenters[i] += cnt;
1544  NNV += origFaces[i].size();
1545  }
1546  vector<TPoint3D> vertices(NNV);
1547  vector<TPolyhedronFace> faces(NF + NV + NE);
1548  size_t ind = 0;
1549  for (size_t i = 0; i < NF; i++)
1550  {
1551  const TPoint3D& oC = polyCenters[i];
1552  const TPoint3D& nC = polyNewCenters[i];
1553  const TPolygon3D& oP = origFaces[i];
1554  vector<uint32_t>& f = faces[i].vertices;
1555  size_t oPS = oP.size();
1556  for (size_t j = 0; j < oPS; j++)
1557  {
1558  vertices[j + ind] = nC + (oP[j] - oC);
1559  f.push_back(j + ind);
1560  size_t curr = mFaces[i].vertices[j];
1561  faces[NF + curr].vertices.push_back(j + ind);
1562  size_t edge;
1563  searchForEdge(
1564  mEdges, curr, mFaces[i].vertices[(j + oPS - 1) % oPS], edge);
1565  faces[NF + NV + edge].vertices.push_back(j + ind);
1566  searchForEdge(
1567  mEdges, curr, mFaces[i].vertices[(j + 1) % oPS], edge);
1568  faces[NF + NV + edge].vertices.push_back(j + ind);
1569  }
1570  ind += oPS;
1571  }
1573  edgeBegin = faces.begin() + NF + NV,
1574  end = faces.end();
1575  for (vector<TPolyhedronFace>::iterator it = faces.begin() + NF;
1576  it != faces.begin() + NF + NV; ++it)
1577  {
1578  vector<uint32_t>& f = it->vertices;
1579  if (f.size() == 3) continue;
1580  for (size_t i = 1; i < f.size() - 1; i++)
1581  for (;;)
1582  if (searchForEdge(edgeBegin, end, f[i - 1], f[i]))
1583  break;
1584  else
1585  {
1586  uint32_t tmp = f[i];
1587  f.erase(f.begin() + i);
1588  f.push_back(tmp);
1589  }
1590  }
1591  for (vector<TPolyhedronFace>::iterator it = faces.begin() + NF + NV;
1592  it != faces.end(); ++it)
1593  {
1594  vector<uint32_t>& f =
1595  it->vertices; // Will always have exactly 4 vertices
1596  for (size_t i = 1; i < 3; i++)
1597  for (;;)
1598  if (searchForEdge(begin, edgeBegin, f[i - 1], f[i]))
1599  break;
1600  else
1601  {
1602  uint32_t tmp = f[i];
1603  f.erase(f.begin() + i);
1604  f.push_back(tmp);
1605  }
1606  }
1607  return mrpt::make_aligned_shared<CPolyhedron>(vertices, faces);
1608 }
1609 
1611 {
1612  size_t NV = mVertices.size();
1613  size_t NF = mFaces.size();
1614  vector<TPoint3D> vertices(NV + NF);
1615  std::copy(mVertices.begin(), mVertices.end(), vertices.begin());
1616  size_t tnf = 0;
1618  it != mFaces.end(); ++it)
1619  tnf += it->vertices.size();
1620  vector<TPolyhedronFace> faces(tnf);
1621  TPolygon3D tmp;
1622  TPlane pTmp;
1623  TPoint3D cTmp;
1624  size_t iF = 0;
1625  TPoint3D phCenter;
1626  getCenter(phCenter);
1627  TPolyhedronFace fTmp;
1628  fTmp.vertices.resize(3);
1629  for (size_t i = 0; i < NF; i++)
1630  {
1631  TPoint3D& vertex = vertices[NV + i];
1632  const vector<uint32_t>& face = mFaces[i].vertices;
1633  size_t N = face.size();
1634  tmp.resize(N);
1635  for (size_t j = 0; j < N; j++) tmp[j] = mVertices[face[j]];
1636  tmp.getBestFittingPlane(pTmp);
1637  pTmp.unitarize();
1638  tmp.getCenter(cTmp);
1639  if (pTmp.evaluatePoint(phCenter) > 0)
1640  for (size_t j = 0; j < 3; j++)
1641  vertex[j] = cTmp[j] - height * pTmp.coefs[j];
1642  else
1643  for (size_t j = 0; j < 3; j++)
1644  vertex[j] = cTmp[j] + height * pTmp.coefs[j];
1645  fTmp.vertices[0] = NV + i;
1646  for (size_t j = 0; j < N; j++)
1647  {
1648  fTmp.vertices[1] = face[j];
1649  fTmp.vertices[2] = face[(j + 1) % N];
1650  faces[iF + j] = fTmp;
1651  }
1652  iF += N;
1653  }
1654  return CreateNoCheck(vertices, faces);
1655 }
1656 
1657 CPolyhedron::Ptr CPolyhedron::augment(double height, size_t numVertices) const
1658 {
1659  size_t NV = mVertices.size();
1660  size_t NF = mFaces.size();
1661  size_t tnf = 0;
1662  size_t tnv = NV;
1664  it != mFaces.end(); ++it)
1665  if (it->vertices.size() == numVertices)
1666  {
1667  tnf += numVertices;
1668  tnv++;
1669  }
1670  else
1671  tnf++;
1672  if (tnv == NV) return CreateNoCheck(mVertices, mFaces);
1673  vector<TPoint3D> vertices(tnv);
1674  std::copy(mVertices.begin(), mVertices.end(), vertices.begin());
1675  vector<TPolyhedronFace> faces(tnf);
1676  TPolygon3D tmp(numVertices);
1677  TPlane pTmp;
1678  TPoint3D cTmp;
1679  size_t iF = 0;
1680  size_t iV = NV;
1681  TPoint3D phCenter;
1682  getCenter(phCenter);
1683  TPolyhedronFace fTmp;
1684  fTmp.vertices.resize(3);
1685  for (size_t i = 0; i < NF; i++)
1686  {
1687  const vector<uint32_t>& face = mFaces[i].vertices;
1688  size_t N = face.size();
1689  if (N != numVertices)
1690  {
1691  faces[iF].vertices = face;
1692  iF++;
1693  continue;
1694  }
1695  TPoint3D& vertex = vertices[iV];
1696  for (size_t j = 0; j < numVertices; j++) tmp[j] = mVertices[face[j]];
1697  tmp.getBestFittingPlane(pTmp);
1698  pTmp.unitarize();
1699  tmp.getCenter(cTmp);
1700  if (pTmp.evaluatePoint(phCenter) > 0)
1701  for (size_t j = 0; j < 3; j++)
1702  vertex[j] = cTmp[j] - height * pTmp.coefs[j];
1703  else
1704  for (size_t j = 0; j < 3; j++)
1705  vertex[j] = cTmp[j] + height * pTmp.coefs[j];
1706  fTmp.vertices[0] = iV;
1707  for (size_t j = 0; j < N; j++)
1708  {
1709  fTmp.vertices[1] = face[j];
1710  fTmp.vertices[2] = face[(j + 1) % N];
1711  faces[iF + j] = fTmp;
1712  }
1713  iF += N;
1714  iV++;
1715  }
1716  return CreateNoCheck(vertices, faces);
1717 }
1718 
1720 {
1721  size_t NV = mVertices.size();
1722  size_t NF = mFaces.size();
1723  vector<TPoint3D> vertices(NV + NF);
1724  std::copy(mVertices.begin(), mVertices.end(), vertices.begin());
1725  size_t tnf = 0;
1727  it != mFaces.end(); ++it)
1728  tnf += it->vertices.size();
1729  vector<TPolyhedronFace> faces(tnf);
1730  TPolygon3D tmp;
1731  TPlane pTmp;
1732  TPoint3D cTmp;
1733  size_t iF = 0;
1734  TPoint3D phCenter;
1735  getCenter(phCenter);
1736  TPolyhedronFace fTmp;
1737  fTmp.vertices.resize(3);
1738  for (size_t i = 0; i < NF; i++)
1739  {
1740  TPoint3D& vertex = vertices[NV + i];
1741  const vector<uint32_t>& face = mFaces[i].vertices;
1742  size_t N = face.size();
1743  tmp.resize(N);
1744  for (size_t j = 0; j < N; j++) tmp[j] = mVertices[face[j]];
1745  tmp.getCenter(cTmp);
1746  double height = getHeight(tmp, cTmp); // throws std::logic_error
1747  tmp.getBestFittingPlane(pTmp);
1748  pTmp.unitarize();
1749  if ((pTmp.evaluatePoint(phCenter) < 0) == direction)
1750  for (size_t j = 0; j < 3; j++)
1751  vertex[j] = cTmp[j] - height * pTmp.coefs[j];
1752  else
1753  for (size_t j = 0; j < 3; j++)
1754  vertex[j] = cTmp[j] + height * pTmp.coefs[j];
1755  fTmp.vertices[0] = NV + i;
1756  for (size_t j = 0; j < N; j++)
1757  {
1758  fTmp.vertices[1] = face[j];
1759  fTmp.vertices[2] = face[(j + 1) % N];
1760  faces[iF + j] = fTmp;
1761  }
1762  iF += N;
1763  }
1764  return CreateNoCheck(vertices, faces);
1765 }
1766 
1767 CPolyhedron::Ptr CPolyhedron::augment(size_t numVertices, bool direction) const
1768 {
1769  size_t NV = mVertices.size();
1770  size_t NF = mFaces.size();
1771  size_t tnf = 0;
1772  size_t tnv = NV;
1774  it != mFaces.end(); ++it)
1775  if (it->vertices.size() == numVertices)
1776  {
1777  tnf += numVertices;
1778  tnv++;
1779  }
1780  else
1781  tnf++;
1782  if (tnv == NV) return CreateNoCheck(mVertices, mFaces);
1783  vector<TPoint3D> vertices(tnv);
1784  std::copy(mVertices.begin(), mVertices.end(), vertices.begin());
1785  vector<TPolyhedronFace> faces(tnf);
1786  TPolygon3D tmp(numVertices);
1787  TPlane pTmp;
1788  TPoint3D cTmp;
1789  size_t iF = 0;
1790  size_t iV = NV;
1791  TPoint3D phCenter;
1792  getCenter(phCenter);
1793  TPolyhedronFace fTmp;
1794  fTmp.vertices.resize(3);
1795  for (size_t i = 0; i < NF; i++)
1796  {
1797  const vector<uint32_t>& face = mFaces[i].vertices;
1798  size_t N = face.size();
1799  if (N != numVertices)
1800  {
1801  faces[iF].vertices = face;
1802  iF++;
1803  continue;
1804  }
1805  TPoint3D& vertex = vertices[iV];
1806  for (size_t j = 0; j < numVertices; j++) tmp[j] = mVertices[face[j]];
1807  tmp.getBestFittingPlane(pTmp);
1808  pTmp.unitarize();
1809  tmp.getCenter(cTmp);
1810  double height = getHeight(tmp, cTmp); // throws std::logic_error
1811  if ((pTmp.evaluatePoint(phCenter) < 0) == direction)
1812  for (size_t j = 0; j < 3; j++)
1813  vertex[j] = cTmp[j] - height * pTmp.coefs[j];
1814  else
1815  for (size_t j = 0; j < 3; j++)
1816  vertex[j] = cTmp[j] + height * pTmp.coefs[j];
1817  fTmp.vertices[0] = iV;
1818  for (size_t j = 0; j < N; j++)
1819  {
1820  fTmp.vertices[1] = face[j];
1821  fTmp.vertices[2] = face[(j + 1) % N];
1822  faces[iF + j] = fTmp;
1823  }
1824  iF += N;
1825  iV++;
1826  }
1827  return CreateNoCheck(vertices, faces);
1828 }
1829 
1831 {
1832  vector<TPoint3D> vertices(mVertices);
1833  double c = cos(angle), s = sin(angle);
1834  for (vector<TPoint3D>::iterator it = vertices.begin(); it != vertices.end();
1835  ++it)
1836  {
1837  double A = it->x;
1838  double B = it->y;
1839  it->x = A * c - B * s;
1840  it->y = B * c + A * s;
1841  }
1842  return CreateNoCheck(vertices, mFaces);
1843 }
1844 
1846 {
1847  vector<TPoint3D> vertices(mVertices);
1848  if (factor <= 0)
1849  throw std::logic_error("Factor must be a strictly positive number");
1850  for (vector<TPoint3D>::iterator it = vertices.begin(); it != vertices.end();
1851  ++it)
1852  {
1853  it->x *= factor;
1854  it->y *= factor;
1855  }
1856  return CreateNoCheck(vertices, mFaces);
1857 }
1858 
1859 vector<TPoint2D> CPolyhedron::generateBase(
1860  uint32_t numBaseEdges, double baseRadius)
1861 {
1862  vector<TPoint2D> base(numBaseEdges);
1863  for (size_t i = 0; i < numBaseEdges; i++)
1864  {
1865  double ang = 2 * M_PI * i / numBaseEdges;
1866  base[i].x = baseRadius * cos(ang);
1867  base[i].y = baseRadius * sin(ang);
1868  }
1869  return base;
1870 }
1871 
1873  uint32_t numBaseEdges, double baseRadius)
1874 {
1875  vector<TPoint2D> base(numBaseEdges);
1876  double shift = M_PI / numBaseEdges;
1877  for (size_t i = 0; i < numBaseEdges; i++)
1878  {
1879  double ang = shift + 2 * M_PI * i / numBaseEdges;
1880  base[i].x = baseRadius * cos(ang);
1881  base[i].y = baseRadius * sin(ang);
1882  }
1883  return base;
1884 }
1885 
1887  uint32_t numBaseEdges, double baseRadius, double height,
1888  vector<TPoint3D>& vec)
1889 {
1890  for (size_t i = 0; i < numBaseEdges; i++)
1891  {
1892  double ang = 2 * M_PI * i / numBaseEdges;
1893  vec.push_back(
1894  TPoint3D(baseRadius * cos(ang), baseRadius * sin(ang), height));
1895  }
1896 }
1897 
1899  uint32_t numBaseEdges, double baseRadius, double height, double shift,
1900  vector<TPoint3D>& vec)
1901 {
1902  for (size_t i = 0; i < numBaseEdges; i++)
1903  {
1904  double ang = 2 * M_PI * i / numBaseEdges + shift;
1905  vec.push_back(
1906  TPoint3D(baseRadius * cos(ang), baseRadius * sin(ang), height));
1907  }
1908 }
1909 
1911 {
1912  tempPolygons.resize(mFaces.size());
1913  transform(
1914  mFaces.begin(), mFaces.end(), tempPolygons.begin(),
1916  polygonsUpToDate = true;
1917 }
1918 
1920 {
1921  size_t N = doCheck ? f.vertices.size() : 3;
1922  TPolygon3D poly(N);
1923  for (size_t i = 0; i < N; i++) poly[i] = mVertices[f.vertices[i]];
1924  TPlane tmp;
1925  if (!poly.getPlane(tmp)) return false;
1926  tmp.getNormalVector(f.normal);
1927  TPoint3D c;
1928  getCenter(c);
1929  if (tmp.evaluatePoint(c) > 0)
1930  for (size_t i = 0; i < 3; i++) f.normal[i] = -f.normal[i];
1931  return true;
1932 }
1933 
1935 {
1936  TPolyhedronEdge e;
1938  e.v1 = *it;
1939  ++it;
1940  while (it != f.vertices.end())
1941  {
1942  e.v2 = *it;
1943  if (find(mEdges.begin(), mEdges.end(), e) == mEdges.end())
1944  mEdges.push_back(e);
1945  e.v1 = e.v2;
1946  ++it;
1947  }
1948  e.v2 = *(f.vertices.begin());
1949  if (find(mEdges.begin(), mEdges.end(), e) == mEdges.end())
1950  mEdges.push_back(e);
1951 }
1952 
1954  const vector<TPoint3D>& vertices, const vector<TPolyhedronFace>& faces)
1955 {
1956  size_t N = vertices.size();
1957  if (vertices.size() > 0)
1958  for (vector<TPoint3D>::const_iterator it = vertices.begin();
1959  it != vertices.end() - 1; ++it)
1960  for (vector<TPoint3D>::const_iterator it2 = it + 1;
1961  it2 != vertices.end(); ++it2)
1962  if (*it == *it2) return false;
1963  for (vector<TPolyhedronFace>::const_iterator it = faces.begin();
1964  it != faces.end(); ++it)
1965  {
1966  const vector<uint32_t>& e = it->vertices;
1967  for (vector<uint32_t>::const_iterator it2 = e.begin(); it2 != e.end();
1968  ++it2)
1969  if (*it2 >= N) return false;
1970  }
1971  return true;
1972 }
1973 
1974 size_t CPolyhedron::edgesInVertex(size_t vertex) const
1975 {
1976  size_t res = 0;
1978  it != mEdges.end(); ++it)
1979  if (it->v1 == vertex || it->v2 == vertex) res++;
1980  return res;
1981 }
1982 
1983 size_t CPolyhedron::facesInVertex(size_t vertex) const
1984 {
1985  size_t res = 0;
1987  it != mFaces.end(); ++it)
1988  if (find(it->vertices.begin(), it->vertices.end(), vertex) !=
1989  it->vertices.end())
1990  res++;
1991  return res;
1992 }
1993 
1996 {
1997  in >> o.v1 >> o.v2;
1998  return in;
1999 }
2000 
2003 {
2004  out << o.v1 << o.v2;
2005  return out;
2006 }
2007 
2010 {
2011  in >> o.vertices >> o.normal[0] >> o.normal[1] >> o.normal[2];
2012  return in;
2013 }
2014 
2017 {
2018  out << o.vertices << o.normal[0] << o.normal[1] << o.normal[2];
2019  return out;
2020 }
2021 
2022 void CPolyhedron::writeToStream(mrpt::utils::CStream& out, int* version) const
2023 {
2024  if (version)
2025  *version = 0;
2026  else
2027  {
2028  writeToStreamRender(out);
2029  // version 0
2030  out << mVertices << mFaces << mWireframe << mLineWidth;
2031  }
2032 }
2033 
2035 {
2036  switch (version)
2037  {
2038  case 0:
2040  in >> mVertices >> mFaces >> mWireframe >> mLineWidth;
2042  throw std::logic_error("Inconsistent data read from stream");
2043  for (vector<TPolyhedronFace>::iterator it = mFaces.begin();
2044  it != mFaces.end(); ++it)
2045  {
2046  if (!setNormal(*it))
2047  throw std::logic_error("Bad face specification");
2048  addEdges(*it);
2049  }
2050  break;
2051  default:
2053  };
2055 }
2056 
2058  mrpt::math::TPoint3D& bb_min, mrpt::math::TPoint3D& bb_max) const
2059 {
2060  bb_min.x = 0;
2061  bb_min.y = 0;
2062  bb_min.z = 0;
2063 
2064  bb_max.x = 0;
2065  bb_max.y = 0;
2066  bb_max.z = 0;
2067 
2068  // Convert to coordinates of my parent:
2069  m_pose.composePoint(bb_min, bb_min);
2070  m_pose.composePoint(bb_max, bb_max);
2071 }
2072 
2073 /*CPolyhedron::Ptr CPolyhedron::CreateCuboctahedron(double radius) {
2074  if (radius==0) return CreateEmpty();
2075  vector<TPoint3D> verts;
2076  vector<TPolyhedronFace> faces;
2077  double d=radius/sqrt(2.0);
2078  verts.push_back(TPoint3D(d,0,d));
2079  verts.push_back(TPoint3D(0,d,d));
2080  verts.push_back(TPoint3D(0,-d,d));
2081  verts.push_back(TPoint3D(-d,0,d));
2082  verts.push_back(TPoint3D(d,d,0));
2083  verts.push_back(TPoint3D(d,-d,0));
2084  verts.push_back(TPoint3D(-d,d,0));
2085  verts.push_back(TPoint3D(-d,-d,0));
2086  verts.push_back(TPoint3D(d,0,-d));
2087  verts.push_back(TPoint3D(0,d,-d));
2088  verts.push_back(TPoint3D(0,-d,-d));
2089  verts.push_back(TPoint3D(-d,0,-d));
2090  TPolyhedronFace f;
2091  static uint32_t faces3[]={0,1,4, 0,2,5, 1,3,6, 2,3,7, 8,9,4, 8,10,5, 9,11,6,
2092 10,11,7};
2093  static uint32_t faces4[]={0,1,3,2, 8,9,11,10, 0,4,8,5, 1,4,9,6, 2,5,10,7,
2094 3,6,11,7};
2095  for (uint32_t *p=reinterpret_cast<uint32_t
2096 *>(&faces3);p<24+reinterpret_cast<uint32_t *>(&faces3);p+=3) {
2097  f.vertices.insert(f.vertices.begin(),p,p+3);
2098  faces.push_back(f);
2099  f.vertices.clear();
2100  }
2101  for (uint32_t *p=reinterpret_cast<uint32_t
2102 *>(&faces4);p<24+reinterpret_cast<uint32_t *>(&faces4);p+=4) {
2103  f.vertices.insert(f.vertices.begin(),p,p+4);
2104  faces.push_back(f);
2105  f.vertices.clear();
2106  }
2107  return CreateNoCheck(verts,faces);
2108 }*/
2109 
2111 {
2112  CPolyhedron::Ptr tetra =
2113  CreateJohnsonSolidWithConstantBase(3, radius * sqrt(8.0) / 3.0, "P+");
2114  for (vector<TPoint3D>::iterator it = tetra->mVertices.begin();
2115  it != tetra->mVertices.end(); ++it)
2116  it->z -= radius / 3;
2117  return tetra;
2118 }
2120 {
2121  if (radius == 0.0) return CreateEmpty();
2122  double r = radius / sqrt(3.0);
2123  return CreateCubicPrism(-r, r, -r, r, -r, r);
2124 }
2126 {
2127  return CreateJohnsonSolidWithConstantBase(4, radius, "P-P+");
2128 }
2130 {
2131  return CreateIcosahedron(radius / sqrt(15 - 6 * sqrt(5.0)))->getDual();
2132 }
2134 {
2135  double ang = M_PI / 5;
2136  double s2 = 4 * square(sin(ang));
2137  double prop = sqrt(s2 - 1) + sqrt(s2 - 2 + 2 * cos(ang)) / 2;
2138  return CreateJohnsonSolidWithConstantBase(5, radius / prop, "P-AP+", 1);
2139 }
2141 {
2142  return CreateTetrahedron(radius * sqrt(27.0 / 11.0))->truncate(2.0 / 3.0);
2143 }
2145 {
2146  return CreateHexahedron(radius * sqrt(1.5))->truncate(1.0);
2147 }
2149 {
2150  return CreateHexahedron(radius * sqrt(3.0 / (5 - sqrt(8.0))))
2151  ->truncate(2 - sqrt(2.0));
2152 }
2154 {
2155  return CreateOctahedron(radius * 3 / sqrt(5.0))->truncate(2.0 / 3.0);
2156 }
2158  double radius, bool type)
2159 {
2161  8, radius / sqrt(1 + square(sin(M_PI / 8))),
2162  type ? "C-PRC+" : "GC-PRC+", 3);
2163 }
2165 {
2167  10, radius, type ? "GR-R+" : "R-R+", 1);
2168 }
2170 {
2171  return CreateDodecahedron(radius * sqrt(45.0) / sqrt(27 + 6 * sqrt(5.0)))
2172  ->truncate(1 - sqrt(0.2));
2173 }
2175 {
2176  return CreateIcosahedron(radius * sqrt(45.0) / sqrt(25 + 4 * sqrt(5.0)))
2177  ->truncate(2.0 / 3.0);
2178 }
2180 {
2181  return CreateIcosahedron(radius * sqrt(10.0 / (35.0 + 9.0 * sqrt(5.0))))
2182  ->cantellate(1.5 * (sqrt(5.0) - 1));
2183 }
2185 {
2186  return CreateJohnsonSolidWithConstantBase(10, radius, "R+");
2187 }
2189 {
2190  return CreateTruncatedTetrahedron(radius * 3 / sqrt(33.0))->getDual();
2191 }
2193 {
2194  return CreateCuboctahedron(radius / sqrt(2.0))->getDual();
2195 }
2197 {
2198  return CreateTruncatedHexahedron(radius / sqrt((5 - sqrt(8.0))))->getDual();
2199 }
2201 {
2202  return CreateTruncatedOctahedron(radius * sqrt(0.6))->getDual();
2203 }
2205 {
2206  return CreateRhombicuboctahedron(radius / sqrt(7 - sqrt(32.0)), true)
2207  ->getDual();
2208 }
2210 {
2211  return CreateIcosidodecahedron(radius * sqrt(2 / (5 - sqrt(5.0))), true)
2212  ->getDual();
2213 }
2215 {
2216  return CreateTruncatedDodecahedron(radius * sqrt(5 / (25 - 8 * sqrt(5.0))))
2217  ->getDual();
2218 }
2220 {
2221  return CreateTruncatedIcosahedron(radius * sqrt(3 / (17 - 6 * sqrt(5.0))))
2222  ->getDual();
2223 }
2225 {
2226  return CreateRhombicosidodecahedron(radius * 3.0 / sqrt(15 - 2 * sqrt(5.0)))
2227  ->getDual();
2228 }
2230  const TPoint3D& p1, const TPoint3D& p2)
2231 {
2232  return CreateCubicPrism(p1.x, p2.x, p1.y, p2.y, p1.z, p2.z);
2233 }
2235  const vector<TPoint2D>& baseVertices, double height, double ratio)
2236 {
2237  return CreateTruncatedPyramid(baseVertices, height, ratio);
2238 }
2240  const vector<TPoint2D>& baseVertices, double height)
2241 {
2242  return CreateTruncatedPyramid(baseVertices, height, 1.0);
2243 }
2245  uint32_t numBaseEdges, double baseRadius, double height)
2246 {
2247  return CreateCustomAntiprism(
2248  generateBase(numBaseEdges, baseRadius),
2249  generateShiftedBase(numBaseEdges, baseRadius), height);
2250 }
2252  uint32_t numBaseEdges, double baseRadius, double height)
2253 {
2254  return CreateCustomPrism(generateBase(numBaseEdges, baseRadius), height);
2255 }
2257  uint32_t numBaseEdges, double baseRadius, double height)
2258 {
2259  return CreatePyramid(generateBase(numBaseEdges, baseRadius), height);
2260 }
2262  uint32_t numBaseEdges, double baseRadius, double height1, double height2)
2263 {
2264  return CreateDoublePyramid(
2265  generateBase(numBaseEdges, baseRadius), height1, height2);
2266 }
2268  uint32_t numBaseEdges, double baseRadius)
2269 {
2270  return CreateJohnsonSolidWithConstantBase(numBaseEdges, baseRadius, "PR");
2271 }
2273  uint32_t numBaseEdges, double baseRadius)
2274 {
2275  return CreateJohnsonSolidWithConstantBase(numBaseEdges, baseRadius, "A");
2276 }
2278  uint32_t numBaseEdges, double baseRadius, double height, double ratio)
2279 {
2280  return CreateTruncatedPyramid(
2281  generateBase(numBaseEdges, baseRadius), height, ratio);
2282 }
2284  uint32_t numBaseEdges, double baseRadius, double height, double ratio)
2285 {
2287  numBaseEdges, baseRadius, height, ratio);
2288 }
2290  uint32_t numBaseEdges, double baseRadius, double height1, double ratio1,
2291  double height2, double ratio2)
2292 {
2293  return CreateBifrustum(
2294  generateBase(numBaseEdges, baseRadius), height1, ratio1, height2,
2295  ratio2);
2296 }
2298  uint32_t numBaseEdges, double edgeLength)
2299 {
2301  numBaseEdges, edgeLength / (2 * sin(M_PI / numBaseEdges)), "C+");
2302 }
2304  uint32_t numBaseEdges, double height)
2305 {
2306  return CreateArchimedeanRegularAntiprism(numBaseEdges, height)->getDual();
2307 }
2309  uint32_t numBaseEdges, double height)
2310 {
2311  return CreateArchimedeanRegularPrism(numBaseEdges, height)->getDual();
2312 }
2313 
2315  const vector<TPoint3D>& vertices, const vector<TPolyhedronFace>& faces)
2316 {
2317  return CPolyhedron::Ptr(new CPolyhedron(vertices, faces, false));
2318 }
2320 {
2321  return CPolyhedron::Ptr(new CPolyhedron());
2322 }
bool faceContainsEdge(const CPolyhedron::TPolyhedronFace &f, const CPolyhedron::TPolyhedronEdge &e)
bool searchForFace(const vector< CPolyhedron::TPolyhedronFace > &fs, uint32_t v1, uint32_t v2, uint32_t v3)
size_t additionalVertices(JohnsonBodyPart j, uint32_t numBaseEdges)
bool getVerticesAndFaces(const vector< math::TPolygon3D > &polys, vector< TPoint3D > &vertices, vector< CPolyhedron::TPolyhedronFace > &faces)
Definition: CPolyhedron.cpp:49
bool getPlanesIntersection(const vector< const TPlane * > &planes, TPoint3D &pnt)
double getHeight(const TPolygon3D &p, const TPoint3D &c)
bool searchForEdge(const vector< CPolyhedron::TPolyhedronEdge > &es, uint32_t v1, uint32_t v2, size_t &where)
JohnsonBodyPart
Definition: CPolyhedron.cpp:80
@ UPWARDS_PYRAMID
Definition: CPolyhedron.cpp:83
@ ROTATED_DOWNWARDS_CUPOLA
Definition: CPolyhedron.cpp:88
@ PRISM
Definition: CPolyhedron.cpp:89
@ DOWNWARDS_PYRAMID
Definition: CPolyhedron.cpp:84
@ ROTATED_UPWARDS_CUPOLA
Definition: CPolyhedron.cpp:87
@ DOWNWARDS_CUPOLA
Definition: CPolyhedron.cpp:86
@ UPWARDS_ROTUNDA
Definition: CPolyhedron.cpp:91
@ SUP_NO_BODY
Definition: CPolyhedron.cpp:82
@ UPWARDS_CUPOLA
Definition: CPolyhedron.cpp:85
@ INF_NO_BODY
Definition: CPolyhedron.cpp:81
@ ANTIPRISM
Definition: CPolyhedron.cpp:90
@ ROTATED_DOWNWARDS_ROTUNDA
Definition: CPolyhedron.cpp:94
@ ROTATED_UPWARDS_ROTUNDA
Definition: CPolyhedron.cpp:93
@ DOWNWARDS_ROTUNDA
Definition: CPolyhedron.cpp:92
bool analyzeJohnsonPartsString(const std::string &components, uint32_t numBaseEdges, vector< JohnsonBodyPart > &parts)
Definition: CPolyhedron.cpp:96
void insertRotunda(double angleShift, double baseRadius, bool isRotated, bool isUpwards, size_t base, vector< TPoint3D > &verts, vector< CPolyhedron::TPolyhedronFace > &faces)
void insertCupola(size_t numBaseEdges, double angleShift, double baseRadius, double edgeLength, bool isRotated, bool isUpwards, size_t base, vector< TPoint3D > &verts, vector< CPolyhedron::TPolyhedronFace > &faces)
size_t additionalFaces(JohnsonBodyPart j, uint32_t numBaseEdges)
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
#define M_PI
Definition: bits.h:92
FCreatePolygonFromFace(const vector< TPoint3D > &v)
Definition: CPolyhedron.cpp:38
const vector< TPoint3D > & verts
Definition: CPolyhedron.cpp:37
T operator()(const CPolyhedron::TPolyhedronFace &f)
Definition: CPolyhedron.cpp:40
3D polygon, inheriting from std::vector<TPoint3D>
void getBestFittingPlane(TPlane &p) const
Gets the best fitting plane, disregarding whether the polygon actually fits inside or not.
bool getPlane(TPlane &p) const
Gets a plane which contains the polygon.
void getCenter(TPoint3D &p) const
Get polygon's central point.
This class represents arbitrary polyhedra.
Definition: CPolyhedron.h:45
static CPolyhedron::Ptr CreateArchimedeanRegularAntiprism(uint32_t numBaseEdges, double baseRadius)
Creates a regular antiprism whose lateral polygons are equilateral triangles, and so each face of its...
std::vector< TPolyhedronEdge > mEdges
List of polyhedron's edges.
Definition: CPolyhedron.h:115
CPolyhedron::Ptr scale(double factor) const
Scales a polyhedron to a given factor.
bool polygonsUpToDate
Whether the set of actual polygons is up to date or not.
Definition: CPolyhedron.h:137
static CPolyhedron::Ptr CreateCubicPrism(double x1, double x2, double y1, double y2, double z1, double z2)
Creates a cubic prism, given the coordinates of two opposite vertices.
static CPolyhedron::Ptr CreateRegularTruncatedPyramid(uint32_t numBaseEdges, double baseRadius, double height, double ratio)
Creates a regular truncated pyramid whose base is a regular polygon.
static CPolyhedron::Ptr CreateRegularPrism(uint32_t numBaseEdges, double baseRadius, double height)
Creates a regular prism whose base is a regular polygon and whose edges are either parallel or perpen...
static CPolyhedron::Ptr CreateBifrustum(const std::vector< mrpt::math::TPoint2D > &baseVertices, double height1, double ratio1, double height2, double ratio2)
Creates a bifrustum, or double truncated pyramid, given a base which will lie on the XY plane.
void getFacesArea(std::vector< double > &areas) const
Gets a vector with each face's area.
static CPolyhedron::Ptr CreateParallelepiped(const mrpt::math::TPoint3D &base, const mrpt::math::TPoint3D &v1, const mrpt::math::TPoint3D &v2, const mrpt::math::TPoint3D &v3)
Creates a parallelepiped, given a base point and three vectors represented as points.
static CPolyhedron::Ptr CreateRhombicTriacontahedron(double radius)
Creates a rhombic triacontahedron, dual to the icosidodecahedron.
static bool checkConsistence(const std::vector< mrpt::math::TPoint3D > &vertices, const std::vector< TPolyhedronFace > &faces)
Checks whether a set of faces is suitable for a set of vertices.
static CPolyhedron::Ptr CreateTriakisIcosahedron(double radius)
Creates a triakis icosahedron, dual to the truncated dodecahedron.
static CPolyhedron::Ptr CreateNoCheck(const std::vector< mrpt::math::TPoint3D > &vertices, const std::vector< TPolyhedronFace > &faces)
Creates a polyhedron without checking its correctness.
static CPolyhedron::Ptr CreateDeltoidalHexecontahedron(double radius)
Creates a deltoidal hexecontahedron, dual to the rhombicosidodecahedron.
static CPolyhedron::Ptr CreateDoublePyramid(const std::vector< mrpt::math::TPoint2D > &baseVertices, double height1, double height2)
Creates a double pyramid, using a set of 2D vertices which will lie on the XY plane.
static CPolyhedron::Ptr CreateRegularFrustum(uint32_t numBaseEdges, double baseRadius, double height, double ratio)
This is a synonym for CreateRegularTruncatedPyramid.
void getCenter(mrpt::math::TPoint3D &center) const
Gets the center of the polyhedron.
static CPolyhedron::Ptr CreateIcosidodecahedron(double radius, bool type=true)
Creates an icosidodecahedron, with 12 pentagons and 20 triangles (see http://en.wikipedia....
static CPolyhedron::Ptr CreateTriakisOctahedron(double radius)
Creates a triakis octahedron, dual to the truncated hexahedron.
bool traceRay(const mrpt::poses::CPose3D &o, double &dist) const override
Ray trace.
static CPolyhedron::Ptr CreateRhombicuboctahedron(double radius, bool type=true)
Creates a rhombicuboctahedron, with 18 squares and 8 triangles (see http://en.wikipedia....
void InitFromVertAndFaces(const std::vector< mrpt::math::TPoint3D > &vertices, const std::vector< TPolyhedronFace > &faces, bool doCheck=true)
Definition: CPolyhedron.h:920
std::vector< mrpt::math::TPoint3D > mVertices
List of vertices presents in the polyhedron.
Definition: CPolyhedron.h:111
static CPolyhedron::Ptr CreateRegularBifrustum(uint32_t numBaseEdges, double baseRadius, double height1, double ratio1, double height2, double ratio2)
Creates a bifrustum (double truncated pyramid) whose base is a regular polygon lying in the XY plane.
void getEdgesLength(std::vector< double > &lengths) const
Gets a vector with each edge's length.
CPolyhedron::Ptr truncate(double factor) const
Truncates a polyhedron to a given factor.
void addEdges(const TPolyhedronFace &e)
Adds, to the existing list of edges, each edge in a given face.
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const override
Introduces a pure virtual method responsible for writing to a CStream.
std::shared_ptr< CPolyhedron > Ptr
Definition: CPolyhedron.h:46
static CPolyhedron::Ptr CreateCustomAntiprism(const std::vector< mrpt::math::TPoint2D > &bottomBase, const std::vector< mrpt::math::TPoint2D > &topBase, double height)
Creates a custom antiprism, using two custom bases.
static CPolyhedron::Ptr CreateTruncatedPyramid(const std::vector< mrpt::math::TPoint2D > &baseVertices, double height, double ratio)
Creates a truncated pyramid, using a set of vertices which will lie on the XY plane.
CPolyhedron::Ptr augment(double height) const
Augments a polyhedron to a given height.
static CPolyhedron::Ptr CreateRhombicosidodecahedron(double radius)
Creates a rhombicosidodecahedron, consisting of 30 squares, 12 pentagons and 20 triangles (see http:/...
static CPolyhedron::Ptr CreateTruncatedHexahedron(double radius)
Creates a truncated hexahedron, with six octogonal faces and eight triangular ones (see http://en....
void updatePolygons() const
Updates the mutable list of polygons used in rendering and ray tracing.
std::vector< TPolyhedronFace > mFaces
List of polyhedron's faces.
Definition: CPolyhedron.h:119
static CPolyhedron::Ptr CreateCupola(uint32_t numBaseEdges, double edgeLength)
Creates a cupola.
CPolyhedron::Ptr cantellate(double factor) const
Cantellates a polyhedron to a given factor.
static CPolyhedron::Ptr CreateTetrakisHexahedron(double radius)
Creates a tetrakis hexahedron, dual to the truncated octahedron.
static std::vector< mrpt::math::TPoint2D > generateBase(uint32_t numBaseEdges, double baseRadius)
Generates a list of 2D vertices constituting a regular polygon.
static CPolyhedron::Ptr CreateEmpty()
Creates an empty Polyhedron.
static CPolyhedron::Ptr CreateIcosahedron(double radius)
Creates a regular icosahedron (see http://en.wikipedia.org/wiki/Icosahedron).
static CPolyhedron::Ptr CreateCustomPrism(const std::vector< mrpt::math::TPoint2D > &baseVertices, double height)
Creates a custom prism with vertical edges, given any base which will lie on the XY plane.
static CPolyhedron::Ptr CreateDodecahedron(double radius)
Creates a regular dodecahedron (see http://en.wikipedia.org/wiki/Dodecahedron).
static CPolyhedron::Ptr CreateHexahedron(double radius)
Creates a regular cube, also called hexahedron (see http://en.wikipedia.org/wiki/Hexahedron).
size_t facesInVertex(size_t vertex) const
Returns how many faces converge in a given vertex.
std::vector< mrpt::math::TPolygonWithPlane > tempPolygons
Mutable list of actual polygons, maintained for speed.
Definition: CPolyhedron.h:133
static CPolyhedron::Ptr CreateTruncatedDodecahedron(double radius)
Creates a truncated dodecahedron, consisting of 12 dodecagons and 20 triangles (see http://en....
CPolyhedron::Ptr rotate(double angle) const
Rotates a polyhedron around the Z axis a given amount of radians.
static CPolyhedron::Ptr CreateTruncatedIcosahedron(double radius)
Creates a truncated icosahedron, consisting of 20 hexagons and 12 pentagons.
static CPolyhedron::Ptr CreateTetrahedron(double radius)
Creates a regular tetrahedron (see http://en.wikipedia.org/wiki/Tetrahedron).
void render_dl() const override
Render.
void makeConvexPolygons()
Recomputes polygons, if necessary, so that each one is convex.
static CPolyhedron::Ptr CreateRhombicDodecahedron(double radius)
Creates a rhombic dodecahedron, dual to the cuboctahedron.
static CPolyhedron::Ptr CreateCuboctahedron(double radius)
Creates a cuboctahedron, consisting of six square faces and eight triangular ones (see http://en....
void getSetOfPolygons(std::vector< math::TPolygon3D > &vec) const
Gets the polyhedron as a set of polygons.
static CPolyhedron::Ptr CreateTrapezohedron(uint32_t numBaseEdges, double baseRadius, double basesDistance)
Creates a trapezohedron, consisting of 2*N kites, where N is the number of edges in the base.
static CPolyhedron::Ptr CreateTriakisTetrahedron(double radius)
Creates a triakis tetrahedron, dual to the truncated tetrahedron.
static CPolyhedron::Ptr CreateRegularPyramid(uint32_t numBaseEdges, double baseRadius, double height)
Creates a regular pyramid whose base is a regular polygon.
static CPolyhedron::Ptr CreateArchimedeanRegularPrism(uint32_t numBaseEdges, double baseRadius)
Creates a regular prism whose lateral area is comprised of squares, and so each face of its is a regu...
void readFromStream(mrpt::utils::CStream &in, int version) override
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
static CPolyhedron::Ptr CreateTruncatedOctahedron(double radius)
Creates a truncated octahedron, with eight hexagons and eight squares (see http://en....
static CPolyhedron::Ptr CreateRandomPolyhedron(double radius)
Creates a random polyhedron from the static methods.
size_t edgesInVertex(size_t vertex) const
Returns how many edges converge in a given vertex.
bool setNormal(TPolyhedronFace &f, bool doCheck=true)
Calculates the normal vector to a face.
static CPolyhedron::Ptr CreateTruncatedTetrahedron(double radius)
Creates a truncated tetrahedron, consisting of four triangular faces and for hexagonal ones (see http...
double mLineWidth
When displaying as wireframe object, this variable stores the width of the edges.
Definition: CPolyhedron.h:129
static CPolyhedron::Ptr CreatePentagonalRotunda(double radius)
Creates a pentagonal rotunda (half an icosidodecahedron), consisting of six pentagons,...
static CPolyhedron::Ptr CreateJohnsonSolidWithConstantBase(uint32_t numBaseEdges, double baseRadius, const std::string &components, size_t shifts=0)
Creates a series of concatenated solids (most of which are prismatoids) whose base is a regular polyg...
static CPolyhedron::Ptr CreateRegularDoublePyramid(uint32_t numBaseEdges, double baseRadius, double height1, double height2)
Creates a regular double pyramid whose base is a regular polygon.
static CPolyhedron::Ptr CreatePentakisDodecahedron(double radius)
Creates a pentakis dodecahedron, dual to the truncated icosahedron.
static CPolyhedron::Ptr CreateCatalanTrapezohedron(uint32_t numBaseEdges, double height)
Creates a trapezohedron whose dual is exactly an archimedean antiprism.
static CPolyhedron::Ptr CreateFrustum(const std::vector< mrpt::math::TPoint2D > &baseVertices, double height, double ratio)
This is a synonym for CreateTruncatedPyramid.
CPolyhedron()
Basic empty constructor.
Definition: CPolyhedron.h:895
static CPolyhedron::Ptr CreateCatalanDoublePyramid(uint32_t numBaseEdges, double height)
Creates a double pyramid whose dual is exactly an archimedean prism.
void getBoundingBox(mrpt::math::TPoint3D &bb_min, mrpt::math::TPoint3D &bb_max) const override
Evaluates the bounding box of this object (including possible children) in the coordinate frame of th...
static CPolyhedron::Ptr CreatePyramid(const std::vector< mrpt::math::TPoint2D > &baseVertices, double height)
Creates a custom pyramid, using a set of 2D vertices which will lie on the XY plane.
static CPolyhedron::Ptr CreateRegularAntiprism(uint32_t numBaseEdges, double baseRadius, double height)
Creates an antiprism whose base is a regular polygon.
double getVolume() const
Gets the polyhedron volume.
CPolyhedron::Ptr getDual() const
Given a polyhedron, creates its dual.
void getSetOfPolygonsAbsolute(std::vector< math::TPolygon3D > &vec) const
Gets the polyhedron as a set of polygons, with the pose transformation already applied.
static std::vector< mrpt::math::TPoint2D > generateShiftedBase(uint32_t numBaseEdges, double baseRadius)
Generates a list of 2D vertices constituting a regular polygon, with an angle shift which makes it su...
static CPolyhedron::Ptr CreateOctahedron(double radius)
Creates a regular octahedron (see http://en.wikipedia.org/wiki/Octahedron).
bool mWireframe
This flag determines whether the polyhedron will be displayed as a solid object or as a set of edges.
Definition: CPolyhedron.h:124
static CPolyhedron::Ptr CreateDeltoidalIcositetrahedron(double radius)
Creates a deltoidal icositetrahedron, dual to the rhombicuboctahedron.
A renderizable object suitable for rendering with OpenGL's display lists.
EIGEN_STRONG_INLINE void notifyChange() const
Must be called to notify that the object has changed (so, the display list must be updated)
void readFromStreamRender(mrpt::utils::CStream &in)
mrpt::poses::CPose3D m_pose
6D pose wrt the parent coordinate reference.
Definition: CRenderizable.h:57
void writeToStreamRender(utils::CStream &out) const
static void checkOpenGLError()
Checks glGetError and throws an exception if an error situation is found.
mrpt::utils::TColor m_color
Color components in the range [0,255].
Definition: CRenderizable.h:54
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:89
void composePoint(double lx, double ly, double lz, double &gx, double &gy, double &gz, mrpt::math::CMatrixFixedNumeric< double, 3, 3 > *out_jacobian_df_dpoint=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dpose=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dse3=nullptr, bool use_small_rot_approx=false) const
An alternative, slightly more efficient way of doing with G and L being 3D points and P this 6D pose...
Definition: CPose3D.cpp:453
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:42
Scalar * iterator
Definition: eigen_plugins.h:26
const Scalar * const_iterator
Definition: eigen_plugins.h:27
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:29
GLAPI void GLAPIENTRY glEnable(GLenum cap)
#define GL_SRC_ALPHA
Definition: glew.h:286
#define GL_LINES
Definition: glew.h:273
GLAPI void GLAPIENTRY glLineWidth(GLfloat width)
GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
GLAPI void GLAPIENTRY glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz)
GLAPI void GLAPIENTRY glBegin(GLenum mode)
GLAPI void GLAPIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z)
#define GL_BLEND
Definition: glew.h:432
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:287
GLAPI void GLAPIENTRY glEnd(void)
#define GL_POLYGON
Definition: glew.h:281
GLAPI void GLAPIENTRY glDisable(GLenum cap)
GLAPI void GLAPIENTRY glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
#define GL_LIGHTING
Definition: glew.h:385
GLfloat GLfloat v1
Definition: glext.h:4105
GLenum GLsizei n
Definition: glext.h:5074
GLuint GLenum GLenum transform
Definition: glext.h:6975
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
const GLdouble * v
Definition: glext.h:3678
GLuint res
Definition: glext.h:7268
const GLubyte * c
Definition: glext.h:6313
GLuint GLsizei GLsizei * length
Definition: glext.h:4064
GLuint GLuint end
Definition: glext.h:3528
GLenum GLenum GLuint components
Definition: glext.h:7282
GLuint index
Definition: glext.h:4054
GLenum GLint GLint y
Definition: glext.h:3538
GLenum GLuint GLint GLenum face
Definition: glext.h:8194
GLubyte GLubyte b
Definition: glext.h:6279
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3528
GLuint in
Definition: glext.h:7274
GLuint dst
Definition: glext.h:7135
GLenum GLint x
Definition: glext.h:3538
GLfloat GLfloat GLfloat v2
Definition: glext.h:4107
GLubyte g
Definition: glext.h:6279
GLfloat GLfloat p
Definition: glext.h:6305
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
GLdouble GLdouble z
Definition: glext.h:3872
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:4109
GLdouble s
Definition: glext.h:3676
GLenum GLsizei GLsizei height
Definition: glext.h:3554
GLsizei const GLchar ** string
Definition: glext.h:4101
bool splitInConvexComponents(const TPolygon2D &poly, std::vector< TPolygon2D > &components)
Splits a 2D polygon into convex components.
Definition: geometry.cpp:2389
bool traceRay(const std::vector< TPolygonWithPlane > &vec, const mrpt::poses::CPose3D &pose, double &dist)
Fast ray tracing method using polygons' properties.
Definition: geometry.cpp:2582
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
Definition: geometry.cpp:1885
double getEpsilon()
Gets the value of the geometric epsilon (default = 1e-5)
Definition: geometry.cpp:30
bool intersect(const TSegment3D &s1, const TSegment3D &s2, TObject3D &obj)
Gets the intersection between two 3D segments.
Definition: geometry.cpp:635
for(ctr=DCTSIZE;ctr > 0;ctr--)
Definition: jidctflt.cpp:56
INT32 z1
Definition: jidctint.cpp:130
INT32 z2
Definition: jidctint.cpp:130
int val
Definition: mrpt_jpeglib.h:955
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: mrpt_macros.h:181
#define THROW_EXCEPTION(msg)
Definition: mrpt_macros.h:111
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:20
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:16
mrpt::utils::CStream & operator<<(mrpt::utils::CStream &out, const mrpt::opengl::CLight &o)
Definition: CLight.cpp:132
mrpt::utils::CStream & operator>>(mrpt::utils::CStream &in, mrpt::opengl::CLight &o)
Definition: CLight.cpp:126
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:18
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
const_iterator find(const KEY &key) const
Definition: ts_hash_map.h:220
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
This file implements several operations that operate element-wise on individual or pairs of container...
unsigned __int32 uint32_t
Definition: rptypes.h:47
double & operator[](size_t i)
double operator[](size_t i) const
3D line, represented by a base point and a director vector.
Standard object for storing any 3D lightweight object.
3D Plane, represented by its equation
double evaluatePoint(const TPoint3D &point) const
Evaluate a point in the plane's equation.
void getNormalVector(double(&vec)[3]) const
Get plane's normal vector.
double coefs[4]
Plane coefficients, stored as an array: .
void unitarize()
Unitarize normal vector.
Lightweight 3D point.
double x
X,Y,Z coordinates.
Struct used to store a polyhedron edge.
Definition: CPolyhedron.h:53
Struct used to store a polyhedron face.
Definition: CPolyhedron.h:90
std::vector< uint32_t > vertices
Vector of indices to the vertex list.
Definition: CPolyhedron.h:92



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 63ea9d1f1 Thu Nov 23 00:06:53 2017 +0100 at mar 26 may 2026 12:19:29 CEST