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 }
static CPolyhedron::Ptr CreateEmpty()
Creates an empty Polyhedron.
static CPolyhedron::Ptr CreateRhombicuboctahedron(double radius, bool type=true)
Creates a rhombicuboctahedron, with 18 squares and 8 triangles (see http://en.wikipedia.org/wiki/Rhombicuboctahedron), calculated as an elongated square bicupola.
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...
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...
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
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)
static CPolyhedron::Ptr CreateRhombicTriacontahedron(double radius)
Creates a rhombic triacontahedron, dual to the icosidodecahedron.
static CPolyhedron::Ptr CreateIcosidodecahedron(double radius, bool type=true)
Creates an icosidodecahedron, with 12 pentagons and 20 triangles (see http://en.wikipedia.org/wiki/Icosidodecahedron).
void writeToStreamRender(utils::CStream &out) const
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
void addEdges(const TPolyhedronFace &e)
Adds, to the existing list of edges, each edge in a given face.
bool splitInConvexComponents(const TPolygon2D &poly, std::vector< TPolygon2D > &components)
Splits a 2D polygon into convex components.
Definition: geometry.cpp:2389
GLdouble GLdouble z
Definition: glext.h:3872
mrpt::utils::CStream & operator<<(mrpt::utils::CStream &out, const mrpt::opengl::CLight &o)
Definition: CLight.cpp:132
size_t facesInVertex(size_t vertex) const
Returns how many faces converge in a given vertex.
size_t edgesInVertex(size_t vertex) const
Returns how many edges converge in a given vertex.
GLAPI void GLAPIENTRY glEnable(GLenum cap)
JohnsonBodyPart
Definition: CPolyhedron.cpp:79
double getVolume() const
Gets the polyhedron volume.
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...
INT32 z2
Definition: jidctint.cpp:130
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
bool traceRay(const std::vector< TPolygonWithPlane > &vec, const mrpt::poses::CPose3D &pose, double &dist)
Fast ray tracing method using polygons&#39; properties.
Definition: geometry.cpp:2582
void InitFromVertAndFaces(const std::vector< mrpt::math::TPoint3D > &vertices, const std::vector< TPolyhedronFace > &faces, bool doCheck=true)
Definition: CPolyhedron.h:914
static CPolyhedron::Ptr CreateCuboctahedron(double radius)
Creates a cuboctahedron, consisting of six square faces and eight triangular ones (see http://en...
void makeConvexPolygons()
Recomputes polygons, if necessary, so that each one is convex.
#define THROW_EXCEPTION(msg)
bool getVerticesAndFaces(const vector< math::TPolygon3D > &polys, vector< TPoint3D > &vertices, vector< CPolyhedron::TPolyhedronFace > &faces)
Definition: CPolyhedron.cpp:49
static CPolyhedron::Ptr CreateTriakisIcosahedron(double radius)
Creates a triakis icosahedron, dual to the truncated dodecahedron.
GLAPI void GLAPIENTRY glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz)
GLenum GLsizei n
Definition: glext.h:5074
Scalar * iterator
Definition: eigen_plugins.h:26
This file implements several operations that operate element-wise on individual or pairs of container...
CPolyhedron::Ptr getDual() const
Given a polyhedron, creates its dual.
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:29
std::shared_ptr< CPolyhedron > Ptr
Definition: CPolyhedron.h:46
static CPolyhedron::Ptr CreateCatalanDoublePyramid(uint32_t numBaseEdges, double height)
Creates a double pyramid whose dual is exactly an archimedean prism.
size_t additionalFaces(JohnsonBodyPart j, uint32_t numBaseEdges)
for(ctr=DCTSIZE;ctr > 0;ctr--)
Definition: jidctflt.cpp:56
CPolyhedron::Ptr rotate(double angle) const
Rotates a polyhedron around the Z axis a given amount of radians.
Standard object for storing any 3D lightweight object.
EIGEN_STRONG_INLINE void notifyChange() const
Must be called to notify that the object has changed (so, the display list must be updated) ...
static CPolyhedron::Ptr CreateTetrakisHexahedron(double radius)
Creates a tetrakis hexahedron, dual to the truncated octahedron.
static CPolyhedron::Ptr CreateIcosahedron(double radius)
Creates a regular icosahedron (see http://en.wikipedia.org/wiki/Icosahedron).
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...
STL namespace.
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...
#define M_PI
Definition: bits.h:92
const Scalar * const_iterator
Definition: eigen_plugins.h:27
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:287
const_iterator find(const KEY &key) const
Definition: ts_hash_map.h:220
GLenum GLenum GLuint components
Definition: glext.h:7282
bool getPlanesIntersection(const vector< const TPlane *> &planes, TPoint3D &pnt)
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.
GLdouble s
Definition: glext.h:3676
#define GL_POLYGON
Definition: glew.h:281
#define GL_LIGHTING
Definition: glew.h:385
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
GLAPI void GLAPIENTRY glLineWidth(GLfloat width)
mrpt::poses::CPose3D m_pose
6D pose wrt the parent coordinate reference.
Definition: CRenderizable.h:57
static CPolyhedron::Ptr CreateCupola(uint32_t numBaseEdges, double edgeLength)
Creates a cupola.
This class represents arbitrary polyhedra.
Definition: CPolyhedron.h:44
const vector< TPoint3D > & verts
Definition: CPolyhedron.cpp:37
static CPolyhedron::Ptr CreateTriakisTetrahedron(double radius)
Creates a triakis tetrahedron, dual to the truncated tetrahedron.
GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
A renderizable object suitable for rendering with OpenGL&#39;s display lists.
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...
CPolyhedron::Ptr cantellate(double factor) const
Cantellates a polyhedron to a given factor.
bool traceRay(const mrpt::poses::CPose3D &o, double &dist) const override
Ray trace.
static CPolyhedron::Ptr CreateTetrahedron(double radius)
Creates a regular tetrahedron (see http://en.wikipedia.org/wiki/Tetrahedron).
static CPolyhedron::Ptr CreateCatalanTrapezohedron(uint32_t numBaseEdges, double height)
Creates a trapezohedron whose dual is exactly an archimedean antiprism.
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.
static CPolyhedron::Ptr CreateTruncatedDodecahedron(double radius)
Creates a truncated dodecahedron, consisting of 12 dodecagons and 20 triangles (see http://en...
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
std::vector< uint32_t > vertices
Vector of indices to the vertex list.
Definition: CPolyhedron.h:92
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
std::vector< mrpt::math::TPolygonWithPlane > tempPolygons
Mutable list of actual polygons, maintained for speed.
Definition: CPolyhedron.h:133
static CPolyhedron::Ptr CreateRandomPolyhedron(double radius)
Creates a random polyhedron from the static methods.
static CPolyhedron::Ptr CreateFrustum(const std::vector< mrpt::math::TPoint2D > &baseVertices, double height, double ratio)
This is a synonym for CreateTruncatedPyramid.
GLuint dst
Definition: glext.h:7135
static CPolyhedron::Ptr CreateRhombicosidodecahedron(double radius)
Creates a rhombicosidodecahedron, consisting of 30 squares, 12 pentagons and 20 triangles (see http:/...
void insertRotunda(double angleShift, double baseRadius, bool isRotated, bool isUpwards, size_t base, vector< TPoint3D > &verts, vector< CPolyhedron::TPolyhedronFace > &faces)
FCreatePolygonFromFace(const vector< TPoint3D > &v)
Definition: CPolyhedron.cpp:38
static CPolyhedron::Ptr CreatePentagonalRotunda(double radius)
Creates a pentagonal rotunda (half an icosidodecahedron), consisting of six pentagons, ten triangles and a decagon (see http://en.wikipedia.org/wiki/Pentagonal_rotunda).
Struct used to store a polyhedron face.
Definition: CPolyhedron.h:89
void getSetOfPolygons(std::vector< math::TPolygon3D > &vec) const
Gets the polyhedron as a set of polygons.
static CPolyhedron::Ptr CreateTruncatedOctahedron(double radius)
Creates a truncated octahedron, with eight hexagons and eight squares (see http://en.wikipedia.org/wiki/Truncated_octahedron).
GLuint index
Definition: glext.h:4054
const GLubyte * c
Definition: glext.h:6313
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...
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
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 CreateRegularPyramid(uint32_t numBaseEdges, double baseRadius, double height)
Creates a regular pyramid whose base is a regular polygon.
void unitarize()
Unitarize normal vector.
void readFromStreamRender(mrpt::utils::CStream &in)
GLuint GLuint end
Definition: glext.h:3528
CPolyhedron()
Basic empty constructor.
Definition: CPolyhedron.h:889
Struct used to store a polyhedron edge.
Definition: CPolyhedron.h:52
bool searchForEdge(const vector< CPolyhedron::TPolyhedronEdge > &es, uint32_t v1, uint32_t v2, size_t &where)
GLfloat GLfloat GLfloat GLfloat v3
Definition: glext.h:4109
GLubyte g
Definition: glext.h:6279
3D Plane, represented by its equation
static CPolyhedron::Ptr CreateTriakisOctahedron(double radius)
Creates a triakis octahedron, dual to the truncated hexahedron.
int val
Definition: mrpt_jpeglib.h:955
static CPolyhedron::Ptr CreateOctahedron(double radius)
Creates a regular octahedron (see http://en.wikipedia.org/wiki/Octahedron).
bool getPlane(TPlane &p) const
Gets a plane which contains the polygon.
GLubyte GLubyte b
Definition: glext.h:6279
mrpt::utils::TColor m_color
Color components in the range [0,255].
Definition: CRenderizable.h:54
static std::vector< mrpt::math::TPoint2D > generateBase(uint32_t numBaseEdges, double baseRadius)
Generates a list of 2D vertices constituting a regular polygon.
double x
X,Y,Z coordinates.
GLAPI void GLAPIENTRY glBegin(GLenum mode)
#define GL_BLEND
Definition: glew.h:432
GLsizei const GLchar ** string
Definition: glext.h:4101
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.
std::vector< TPolyhedronEdge > mEdges
List of polyhedron&#39;s edges.
Definition: CPolyhedron.h:115
std::vector< mrpt::math::TPoint3D > mVertices
List of vertices presents in the polyhedron.
Definition: CPolyhedron.h:111
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...
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
GLAPI void GLAPIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z)
CPolyhedron::Ptr scale(double factor) const
Scales a polyhedron to a given factor.
GLAPI void GLAPIENTRY glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
size_t additionalVertices(JohnsonBodyPart j, uint32_t numBaseEdges)
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 CreateTruncatedTetrahedron(double radius)
Creates a truncated tetrahedron, consisting of four triangular faces and for hexagonal ones (see http...
mrpt::utils::CStream & operator>>(mrpt::utils::CStream &in, mrpt::opengl::CLight &o)
Definition: CLight.cpp:126
static CPolyhedron::Ptr CreateRegularAntiprism(uint32_t numBaseEdges, double baseRadius, double height)
Creates an antiprism whose base is a regular polygon.
#define GL_SRC_ALPHA
Definition: glew.h:286
static void checkOpenGLError()
Checks glGetError and throws an exception if an error situation is found.
const GLdouble * v
Definition: glext.h:3678
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
bool polygonsUpToDate
Whether the set of actual polygons is up to date or not.
Definition: CPolyhedron.h:137
bool setNormal(TPolyhedronFace &f, bool doCheck=true)
Calculates the normal vector to a face.
bool analyzeJohnsonPartsString(const std::string &components, uint32_t numBaseEdges, vector< JohnsonBodyPart > &parts)
Definition: CPolyhedron.cpp:96
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
GLfloat GLfloat v1
Definition: glext.h:4105
void updatePolygons() const
Updates the mutable list of polygons used in rendering and ray tracing.
static CPolyhedron::Ptr CreateRhombicDodecahedron(double radius)
Creates a rhombic dodecahedron, dual to the cuboctahedron.
static CPolyhedron::Ptr CreateRegularDoublePyramid(uint32_t numBaseEdges, double baseRadius, double height1, double height2)
Creates a regular double pyramid whose base is a regular polygon.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:88
double & operator[](size_t i)
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 writeToStream(mrpt::utils::CStream &out, int *getVersion) const override
Introduces a pure virtual method responsible for writing to a CStream.
static CPolyhedron::Ptr CreateNoCheck(const std::vector< mrpt::math::TPoint3D > &vertices, const std::vector< TPolyhedronFace > &faces)
Creates a polyhedron without checking its correctness.
double coefs[4]
Plane coefficients, stored as an array: .
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
static CPolyhedron::Ptr CreateTruncatedIcosahedron(double radius)
Creates a truncated icosahedron, consisting of 20 hexagons and 12 pentagons.
GLuint GLsizei GLsizei * length
Definition: glext.h:4064
static CPolyhedron::Ptr CreateDodecahedron(double radius)
Creates a regular dodecahedron (see http://en.wikipedia.org/wiki/Dodecahedron).
GLuint in
Definition: glext.h:7274
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:15
static CPolyhedron::Ptr CreateRegularTruncatedPyramid(uint32_t numBaseEdges, double baseRadius, double height, double ratio)
Creates a regular truncated pyramid whose base is a regular polygon.
double evaluatePoint(const TPoint3D &point) const
Evaluate a point in the plane&#39;s equation.
GLAPI void GLAPIENTRY glEnd(void)
CPolyhedron::Ptr truncate(double factor) const
Truncates a polyhedron to a given factor.
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...
GLenum GLint GLint y
Definition: glext.h:3538
static CPolyhedron::Ptr CreateDeltoidalHexecontahedron(double radius)
Creates a deltoidal hexecontahedron, dual to the rhombicosidodecahedron.
static CPolyhedron::Ptr CreateHexahedron(double radius)
Creates a regular cube, also called hexahedron (see http://en.wikipedia.org/wiki/Hexahedron).
void getEdgesLength(std::vector< double > &lengths) const
Gets a vector with each edge&#39;s length.
static CPolyhedron::Ptr CreateRegularFrustum(uint32_t numBaseEdges, double baseRadius, double height, double ratio)
This is a synonym for CreateRegularTruncatedPyramid.
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.
double mLineWidth
When displaying as wireframe object, this variable stores the width of the edges. ...
Definition: CPolyhedron.h:129
T operator()(const CPolyhedron::TPolyhedronFace &f)
Definition: CPolyhedron.cpp:40
void render_dl() const override
Render.
GLfloat GLfloat GLfloat v2
Definition: glext.h:4107
#define GL_LINES
Definition: glew.h:273
double operator[](size_t i) const
GLuint res
Definition: glext.h:7268
GLenum GLint x
Definition: glext.h:3538
void getCenter(mrpt::math::TPoint3D &center) const
Gets the center of the polyhedron.
std::vector< TPolyhedronFace > mFaces
List of polyhedron&#39;s faces.
Definition: CPolyhedron.h:119
void getFacesArea(std::vector< double > &areas) const
Gets a vector with each face&#39;s area.
Lightweight 3D point.
GLuint GLenum GLenum transform
Definition: glext.h:6975
void getBestFittingPlane(TPlane &p) const
Gets the best fitting plane, disregarding whether the polygon actually fits inside or not...
double getHeight(const TPolygon3D &p, const TPoint3D &c)
GLenum GLsizei GLsizei height
Definition: glext.h:3554
double getEpsilon()
Gets the value of the geometric epsilon (default = 1e-5)
Definition: geometry.cpp:30
unsigned __int32 uint32_t
Definition: rptypes.h:47
CRandomGenerator & getRandomGenerator()
A static instance of a CRandomGenerator class, for use in single-thread applications.
GLAPI void GLAPIENTRY glDisable(GLenum cap)
static CPolyhedron::Ptr CreatePentakisDodecahedron(double radius)
Creates a pentakis dodecahedron, dual to the truncated icosahedron.
INT32 z1
Definition: jidctint.cpp:130
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
GLfloat GLfloat p
Definition: glext.h:6305
bool searchForFace(const vector< CPolyhedron::TPolyhedronFace > &fs, uint32_t v1, uint32_t v2, uint32_t v3)
bool intersect(const TSegment3D &s1, const TSegment3D &s2, TObject3D &obj)
Gets the intersection between two 3D segments.
Definition: geometry.cpp:635
static CPolyhedron::Ptr CreateDeltoidalIcositetrahedron(double radius)
Creates a deltoidal icositetrahedron, dual to the rhombicuboctahedron.
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...
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3528
3D polygon, inheriting from std::vector<TPoint3D>
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
Definition: geometry.cpp:1885
void getCenter(TPoint3D &p) const
Get polygon&#39;s central point.
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.
GLenum GLuint GLint GLenum face
Definition: glext.h:8194
CPolyhedron::Ptr augment(double height) const
Augments a polyhedron to a given height.
bool faceContainsEdge(const CPolyhedron::TPolyhedronFace &f, const CPolyhedron::TPolyhedronEdge &e)
static CPolyhedron::Ptr CreateTruncatedHexahedron(double radius)
Creates a truncated hexahedron, with six octogonal faces and eight triangular ones (see http://en...
void getSetOfPolygonsAbsolute(std::vector< math::TPolygon3D > &vec) const
Gets the polyhedron as a set of polygons, with the pose transformation already applied.
void getNormalVector(double(&vec)[3]) const
Get plane&#39;s normal vector.
3D line, represented by a base point and a director vector.



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019