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



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 8fe78517f Sun Jul 14 19:43:28 2019 +0200 at dom jul 14 20:00:11 CEST 2019