Main MRPT website > C++ reference for MRPT 1.9.9
CGeneralizedCylinder.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
12 #include <mrpt/poses/CPose3D.h>
13 #include <mrpt/math/geometry.h>
14 #include <mrpt/math/ops_matrices.h> // for extract*()
15 #include <mrpt/utils/CStream.h>
17 
18 #include "opengl_internals.h"
19 
20 using namespace mrpt;
21 using namespace mrpt::math;
22 using namespace mrpt::opengl;
23 using namespace mrpt::poses;
24 using namespace mrpt::utils;
25 using namespace std;
26 
29 
30 void CGeneralizedCylinder::TQuadrilateral::calculateNormal()
31 {
32  double ax = points[1].x - points[0].x;
33  double ay = points[1].y - points[0].y;
34  double az = points[1].z - points[0].z;
35  double bx = points[2].x - points[0].x;
36  double by = points[2].y - points[0].y;
37  double bz = points[2].z - points[0].z;
38  normal[0] = az * by - ay * bz;
39  normal[1] = ax * bz - az * bx;
40  normal[2] = ay * bx - ax * by;
41  double s = 0;
42  for (size_t i = 0; i < 3; i++) s += normal[i] * normal[i];
43  s = sqrt(s);
44  for (size_t i = 0; i < 3; i++) normal[i] /= s;
45 }
46 
47 #if MRPT_HAS_OPENGL_GLUT
48 class FQuadrilateralRenderer
49 {
50  private:
52 
53  public:
54  void operator()(const CGeneralizedCylinder::TQuadrilateral& t) const
55  {
56  glNormal3d(t.normal[0], t.normal[1], t.normal[2]);
57  for (int i = 0; i < 4; i++)
58  glVertex3d(t.points[i].x, t.points[i].y, t.points[i].z);
59  }
60  FQuadrilateralRenderer(const mrpt::utils::TColor& c) : color(c) {}
61  ~FQuadrilateralRenderer() {}
62 };
63 #endif
64 
65 void CGeneralizedCylinder::getMeshIterators(
66  const vector<TQuadrilateral>& m,
69 {
70  if (fullyVisible)
71  {
72  begin = m.begin();
73  end = m.end();
74  }
75  else
76  {
77  size_t qps =
78  m.size() / getNumberOfSections(); // quadrilaterals per section
79  begin = m.begin() + qps * firstSection;
80  end = m.begin() + qps * lastSection;
81  }
82 }
83 
84 void CGeneralizedCylinder::render_dl() const
85 {
86 #if MRPT_HAS_OPENGL_GLUT
87  if (!meshUpToDate) updateMesh();
91 
93  glColor4ub(m_color.R, m_color.G, m_color.B, m_color.A);
95  getMeshIterators(mesh, begin, end);
96  for_each(begin, end, FQuadrilateralRenderer(m_color));
97  glEnd();
98  if (m_color.A != 1.0) glDisable(GL_BLEND);
99 
100 #endif
101 }
102 
103 inline void createMesh(
104  const CMatrixTemplate<TPoint3D>& pointsMesh, size_t R, size_t C,
105  vector<CGeneralizedCylinder::TQuadrilateral>& mesh)
106 {
107  mesh.reserve(R * C);
108  for (size_t i = 0; i < R; i++)
109  for (size_t j = 0; j < C; j++)
110  mesh.push_back(
112  pointsMesh(i, j), pointsMesh(i, j + 1),
113  pointsMesh(i + 1, j + 1), pointsMesh(i + 1, j)));
114 }
115 
116 /*void transformMesh(const CPose3D &pose,const CMatrixTemplate<TPoint3D>
117 &in,CMatrixTemplate<TPoint3D> &out) {
118  size_t R=in.getRowCount();
119  size_t C=in.getColCount();
120  out.setSize(R,C);
121  for (size_t i=0;i<R;i++) for (size_t j=0;j<C;j++) {
122  TPoint3D pIn=in.get_unsafe(i,j);
123  TPoint3D &pOut=out.get_unsafe(i,j);
124  pose.composePoint(pIn.x,pIn.y,pIn.z,pOut.x,pOut.y,pOut.z);
125  }
126 }*/
127 
128 bool CGeneralizedCylinder::traceRay(const CPose3D& o, double& dist) const
129 {
130  if (!meshUpToDate || !polysUpToDate) updatePolys();
131  return math::traceRay(polys, o - this->m_pose, dist);
132 }
133 
134 void CGeneralizedCylinder::updateMesh() const
135 {
136  CRenderizableDisplayList::notifyChange();
137 
138  size_t A = axis.size();
139  vector<TPoint3D> genX = generatrix;
140  if (closed && genX.size() > 2) genX.push_back(genX[0]);
141  size_t G = genX.size();
142  mesh.clear();
143  if (A > 1 && G > 1)
144  {
145  pointsMesh = CMatrixTemplate<TPoint3D>(A, G);
146  for (size_t i = 0; i < A; i++)
147  for (size_t j = 0; j < G; j++)
148  axis[i].composePoint(genX[j], pointsMesh.get_unsafe(i, j));
149  createMesh(pointsMesh, A - 1, G - 1, mesh);
150  }
151  meshUpToDate = true;
152  polysUpToDate = false;
153 }
154 
155 void CGeneralizedCylinder::writeToStream(
156  mrpt::utils::CStream& out, int* version) const
157 {
158  if (version)
159  *version = 1;
160  else
161  {
162  writeToStreamRender(out);
163  out << axis << generatrix; // In version 0, axis was a
164  // vector<TPoint3D>. In version 1, it is a
165  // vector<CPose3D>.
166  }
167 }
168 
169 void CGeneralizedCylinder::readFromStream(mrpt::utils::CStream& in, int version)
170 {
171  switch (version)
172  {
173  case 0:
174  {
175  readFromStreamRender(in);
176  vector<TPoint3D> a;
177  in >> a >> generatrix;
178  generatePoses(a, axis);
179  meshUpToDate = false;
180  polysUpToDate = false;
181  break;
182  }
183  case 1:
184  readFromStreamRender(in);
185  // version 0
186  in >> axis >> generatrix;
187  meshUpToDate = false;
188  polysUpToDate = false;
189  break;
190  default:
192  };
193  CRenderizableDisplayList::notifyChange();
194 }
195 
197  CPolyhedron::Ptr& poly, const vector<TPoint3D>& profile,
198  const CPose3D& pose)
199 {
200  math::TPolygon3D p(profile.size());
201  for (size_t i = 0; i < profile.size(); i++)
202  pose.composePoint(
203  profile[i].x, profile[i].y, profile[i].z, p[i].x, p[i].y, p[i].z);
204  vector<math::TPolygon3D> convexPolys;
205  if (!math::splitInConvexComponents(p, convexPolys))
206  convexPolys.push_back(p);
207  poly = mrpt::make_aligned_shared<CPolyhedron>(convexPolys);
208 }
209 
210 void CGeneralizedCylinder::getOrigin(CPolyhedron::Ptr& poly) const
211 {
212  if (!meshUpToDate) updateMesh();
213  if (axis.size() < 2 || generatrix.size() < 3)
214  throw std::logic_error("Not enough points.");
215  size_t i = fullyVisible ? 0 : firstSection;
216  generatePolygon(poly, generatrix, axis[i]);
217  poly->setPose(this->m_pose);
218  poly->setColor(getColor());
219 }
220 
221 void CGeneralizedCylinder::getEnd(CPolyhedron::Ptr& poly) const
222 {
223  if (!meshUpToDate) updateMesh();
224  if (axis.size() < 2 || generatrix.size() < 3)
225  throw std::logic_error("Not enough points.");
226  size_t i = (fullyVisible ? axis.size() : lastSection) - 1;
227  generatePolygon(poly, generatrix, axis[i]);
228  poly->setPose(this->m_pose);
229  poly->setColor(getColor());
230 }
231 
232 void CGeneralizedCylinder::generateSetOfPolygons(
233  std::vector<TPolygon3D>& res) const
234 {
235  if (!meshUpToDate || !polysUpToDate) updatePolys();
236  size_t N = polys.size();
237  res.resize(N);
238  for (size_t i = 0; i < N; i++) res[i] = polys[i].poly;
239 }
240 
241 void CGeneralizedCylinder::getClosedSection(
242  size_t index1, size_t index2, mrpt::opengl::CPolyhedron::Ptr& poly) const
243 {
244  if (index1 > index2) swap(index1, index2);
245  if (index2 >= axis.size() - 1) throw std::logic_error("Out of range");
246  CMatrixTemplate<TPoint3D> ROIpoints;
247  if (!meshUpToDate) updateMesh();
248  pointsMesh.extractRows(index1, index2 + 1, ROIpoints);
249  // At this point, ROIpoints contains a matrix of TPoints in which the number
250  // of rows equals (index2-index1)+2 and there is a column
251  // for each vertex in the generatrix.
252  if (!closed)
253  {
254  vector<TPoint3D> vec;
255  ROIpoints.extractCol(0, vec);
256  ROIpoints.appendCol(vec);
257  }
258  vector<TPoint3D> vertices;
259  ROIpoints.getAsVector(vertices);
260  size_t nr = ROIpoints.getRowCount() - 1;
261  size_t nc = ROIpoints.getColCount() - 1;
262  vector<vector<uint32_t>> faces;
263  faces.reserve(nr * nc + 2);
264  vector<uint32_t> tmp(4);
265  for (size_t i = 0; i < nr; i++)
266  for (size_t j = 0; j < nc; j++)
267  {
268  size_t base = (nc + 1) * i + j;
269  tmp[0] = base;
270  tmp[1] = base + 1;
271  tmp[2] = base + nc + 2;
272  tmp[3] = base + nc + 1;
273  faces.push_back(tmp);
274  }
275  tmp.resize(nr + 1);
276  for (size_t i = 0; i < nr + 1; i++) tmp[i] = i * (nc + 1);
277  faces.push_back(tmp);
278  for (size_t i = 0; i < nr + 1; i++) tmp[i] = i * (nc + 2) - 1;
279  poly = mrpt::make_aligned_shared<CPolyhedron>(vertices, faces);
280 }
281 
282 void CGeneralizedCylinder::removeVisibleSectionAtStart()
283 {
284  CRenderizableDisplayList::notifyChange();
285  if (fullyVisible)
286  {
287  if (!getNumberOfSections()) throw std::logic_error("No more sections");
288  fullyVisible = false;
289  firstSection = 1;
290  lastSection = getNumberOfSections();
291  }
292  else if (firstSection >= lastSection)
293  throw std::logic_error("No more sections");
294  else
295  firstSection++;
296 }
297 void CGeneralizedCylinder::removeVisibleSectionAtEnd()
298 {
299  CRenderizableDisplayList::notifyChange();
300  if (fullyVisible)
301  {
302  if (!getNumberOfSections()) throw std::logic_error("No more sections");
303  fullyVisible = false;
304  firstSection = 0;
305  lastSection = getNumberOfSections() - 1;
306  }
307  else if (firstSection >= lastSection)
308  throw std::logic_error("No more sections");
309  else
310  lastSection--;
311 }
312 
313 void CGeneralizedCylinder::updatePolys() const
314 {
315  CRenderizableDisplayList::notifyChange();
316 
317  if (!meshUpToDate) updateMesh();
318  size_t N = mesh.size();
319  polys.resize(N);
320  TPolygon3D tmp(4);
321  for (size_t i = 0; i < N; i++)
322  {
323  for (size_t j = 0; j < 4; j++) tmp[j] = mesh[i].points[j];
324  polys[i] = tmp;
325  }
326  polysUpToDate = true;
327 }
328 
329 void CGeneralizedCylinder::generatePoses(
330  const vector<TPoint3D>& pIn,
332 {
333  size_t N = pIn.size();
334  if (N == 0)
335  {
336  pOut.resize(0);
337  return;
338  }
339  vector<double> yaws;
340  yaws.reserve(N);
341  vector<TPoint3D>::const_iterator it1 = pIn.begin(), it2;
342  for (;;)
343  if ((it2 = it1 + 1) == pIn.end())
344  break;
345  else
346  {
347  yaws.push_back(atan2(it2->y - it1->y, it2->x - it1->x));
348  it1 = it2;
349  }
350  yaws.push_back(*yaws.rbegin());
351  pOut.resize(N);
352  for (size_t i = 0; i < N; i++)
353  {
354  const TPoint3D& p = pIn[i];
355  pOut[i] = CPose3D(p.x, p.y, p.z, yaws[i], 0, 0);
356  }
357 }
358 
359 bool CGeneralizedCylinder::getFirstSectionPose(CPose3D& p)
360 {
361  if (axis.size() <= 0) return false;
362  p = axis[0];
363  return true;
364 }
365 
366 bool CGeneralizedCylinder::getLastSectionPose(CPose3D& p)
367 {
368  if (axis.size() <= 0) return false;
369  p = *axis.rbegin();
370  return true;
371 }
372 
373 bool CGeneralizedCylinder::getFirstVisibleSectionPose(CPose3D& p)
374 {
375  if (fullyVisible) return getFirstSectionPose(p);
376  if (getVisibleSections() <= 0) return false;
377  p = axis[firstSection];
378  return true;
379 }
380 
381 bool CGeneralizedCylinder::getLastVisibleSectionPose(CPose3D& p)
382 {
383  if (fullyVisible) return getLastSectionPose(p);
384  if (getVisibleSections() <= 0) return false;
385  p = axis[lastSection];
386  return true;
387 }
388 
389 void CGeneralizedCylinder::getBoundingBox(
390  mrpt::math::TPoint3D& bb_min, mrpt::math::TPoint3D& bb_max) const
391 {
392  bb_min = TPoint3D(0, 0, 0);
393  bb_max = TPoint3D(0, 0, 0);
394 
395  // Convert to coordinates of my parent:
396  m_pose.composePoint(bb_min, bb_min);
397  m_pose.composePoint(bb_max, bb_max);
398 }
void generatePolygon(CPolyhedron::Ptr &poly, const vector< TPoint3D > &profile, const CPose3D &pose)
void createMesh(const CMatrixTemplate< TPoint3D > &pointsMesh, size_t R, size_t C, vector< CGeneralizedCylinder::TQuadrilateral > &mesh)
IMPLEMENTS_SERIALIZABLE(CGeneralizedCylinder, CRenderizableDisplayList, mrpt::opengl) void CGeneralizedCylinder
const float R
This template class provides the basic functionality for a general 2D any-size, resizable container o...
void appendCol(const std::vector< T > &in)
Appends a new column to the matrix from a vector.
void extractCol(size_t nCol, std::vector< T > &out, int startingRow=0) const
Returns a given column to a vector (without modifying the matrix)
size_t getColCount() const
Number of columns in the matrix.
void getAsVector(std::vector< T > &out) const
Returns a vector containing the matrix's values.
size_t getRowCount() const
Number of rows in the matrix.
3D polygon, inheriting from std::vector<TPoint3D>
This object represents any figure obtained by extruding any profile along a given axis.
std::shared_ptr< CPolyhedron > Ptr
Definition: CPolyhedron.h:46
A renderizable object suitable for rendering with OpenGL's display lists.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:89
void composePoint(double lx, double ly, double lz, double &gx, double &gy, double &gz, mrpt::math::CMatrixFixedNumeric< double, 3, 3 > *out_jacobian_df_dpoint=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dpose=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dse3=nullptr, bool use_small_rot_approx=false) const
An alternative, slightly more efficient way of doing with G and L being 3D points and P this 6D pose...
Definition: CPose3D.cpp:453
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:42
const Scalar * const_iterator
Definition: eigen_plugins.h:27
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:29
GLAPI void GLAPIENTRY glEnable(GLenum cap)
#define GL_QUADS
Definition: glew.h:279
GLAPI void GLAPIENTRY glNormal3d(GLdouble nx, GLdouble ny, GLdouble nz)
#define GL_SRC_ALPHA
Definition: glew.h:286
GLAPI void GLAPIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
GLAPI void GLAPIENTRY glBegin(GLenum mode)
#define GL_BLEND
Definition: glew.h:432
#define GL_ONE_MINUS_SRC_ALPHA
Definition: glew.h:287
GLAPI void GLAPIENTRY glEnd(void)
GLAPI void GLAPIENTRY glDisable(GLenum cap)
GLAPI void GLAPIENTRY glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
GLAPI void GLAPIENTRY glVertex3d(GLdouble x, GLdouble y, GLdouble z)
GLdouble GLdouble t
Definition: glext.h:3689
GLbyte GLbyte bz
Definition: glext.h:6105
GLuint res
Definition: glext.h:7268
const GLubyte * c
Definition: glext.h:6313
GLuint color
Definition: glext.h:8300
GLuint GLuint end
Definition: glext.h:3528
GLuint in
Definition: glext.h:7274
GLfloat GLfloat p
Definition: glext.h:6305
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
GLdouble s
Definition: glext.h:3676
GLsizei const GLfloat * points
Definition: glext.h:5339
GLbyte by
Definition: glext.h:6105
bool splitInConvexComponents(const TPolygon2D &poly, std::vector< TPolygon2D > &components)
Splits a 2D polygon into convex components.
Definition: geometry.cpp:2389
bool traceRay(const std::vector< TPolygonWithPlane > &vec, const mrpt::poses::CPose3D &pose, double &dist)
Fast ray tracing method using polygons' properties.
Definition: geometry.cpp:2582
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Definition: mrpt_macros.h:181
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:20
void checkOpenGLError()
Checks glGetError and throws an exception if an error situation is found.
Definition: gl_utils.cpp:140
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:16
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:18
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
This file implements miscelaneous matrix and matrix/vector operations, and internal functions in mrpt...
std::vector< TYPE1, Eigen::aligned_allocator< TYPE1 > > vector_t
Lightweight 3D point.
Auxiliary struct holding any quadrilateral, represented by foour points.
A RGB color - 8bit.
Definition: TColor.h:26



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