Main MRPT website > C++ reference for MRPT 1.9.9
lightweight_geom_data.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 "base-precomp.h" // Precompiled headers
11 
13 #include <mrpt/poses/CPoint2D.h>
14 #include <mrpt/poses/CPoint3D.h>
15 #include <mrpt/poses/CPose2D.h>
16 #include <mrpt/poses/CPose3DQuat.h>
17 #include <mrpt/math/CQuaternion.h>
18 #include <mrpt/math/geometry.h>
20 #include <mrpt/utils/CStream.h>
22 
23 using namespace std; // For min/max, etc...
24 
25 namespace mrpt
26 {
27 namespace math
28 {
29 using namespace mrpt::poses; // For the +,- operators
30 using namespace mrpt::utils;
31 
32 namespace detail
33 {
34 // Convert a pose into a light-weight structure (functional form, needed for
35 // forward declarations)
41 {
42  return TPose3DQuat(p);
43 }
44 
45 } // end detail
46 
47 TPoint2D::TPoint2D(const TPose2D& p) : x(p.x), y(p.y) {}
48 TPoint2D::TPoint2D(const TPoint3D& p) : x(p.x), y(p.y) {}
49 TPoint2D::TPoint2D(const TPose3D& p) : x(p.x), y(p.y) {}
51 bool TPoint2D::operator<(const TPoint2D& p) const
52 {
53  if (x < p.x)
54  return true;
55  else if (x > p.x)
56  return false;
57  else
58  return y < p.y;
59 }
61 {
62  CMatrixDouble m;
63  if (!m.fromMatlabStringFormat(s))
64  THROW_EXCEPTION("Malformed expression in ::fromString");
65  ASSERTMSG_(
66  mrpt::math::size(m, 1) == 1 && mrpt::math::size(m, 2) == 2,
67  "Wrong size of vector in ::fromString");
68  x = m.get_unsafe(0, 0);
69  y = m.get_unsafe(0, 1);
70 }
71 
72 TPose2D::TPose2D(const TPoint2D& p) : x(p.x), y(p.y), phi(0.0) {}
73 TPose2D::TPose2D(const TPoint3D& p) : x(p.x), y(p.y), phi(0.0) {}
74 TPose2D::TPose2D(const TPose3D& p) : x(p.x), y(p.y), phi(p.yaw) {}
76  : x(p.x()), y(p.y()), phi(p.phi())
77 {
78 }
80 {
81  s = mrpt::format("[%f %f %f]", x, y, mrpt::utils::RAD2DEG(phi));
82 }
84 {
85  CMatrixDouble m;
86  if (!m.fromMatlabStringFormat(s))
87  THROW_EXCEPTION("Malformed expression in ::fromString");
88  ASSERTMSG_(
89  mrpt::math::size(m, 1) == 1 && mrpt::math::size(m, 2) == 3,
90  "Wrong size of vector in ::fromString");
91  x = m.get_unsafe(0, 0);
92  y = m.get_unsafe(0, 1);
93  phi = DEG2RAD(m.get_unsafe(0, 2));
94 }
96  const mrpt::math::TPose2D& b) const
97 {
98  const double A_cosphi = cos(this->phi), A_sinphi = sin(this->phi);
99  // Use temporary variables for the cases (A==this) or (B==this)
100  const double new_x = this->x + b.x * A_cosphi - b.y * A_sinphi;
101  const double new_y = this->y + b.x * A_cosphi + b.y * A_sinphi;
102  const double new_phi = mrpt::math::wrapToPi(this->phi + b.phi);
103 
104  return mrpt::math::TPose2D(new_x, new_y, new_phi);
105 }
106 
108  const mrpt::math::TPose2D& b) const
109 {
110  const double B_cosphi = cos(b.phi), B_sinphi = sin(b.phi);
111 
112  const double new_x =
113  (this->x - b.x) * B_cosphi + (this->y - b.y) * B_sinphi;
114  const double new_y =
115  -(this->x - b.x) * B_sinphi + (this->y - b.y) * B_cosphi;
116  const double new_phi = mrpt::math::wrapToPi(this->phi - b.phi);
117 
118  return mrpt::math::TPose2D(new_x, new_y, new_phi);
119 }
120 
121 // ----
123 {
124  s = mrpt::format("[%f %f %f]", vx, vy, mrpt::utils::RAD2DEG(omega));
125 }
127 {
128  CMatrixDouble m;
129  if (!m.fromMatlabStringFormat(s))
130  THROW_EXCEPTION("Malformed expression in ::fromString");
131  ASSERTMSG_(
132  mrpt::math::size(m, 1) == 1 && mrpt::math::size(m, 2) == 3,
133  "Wrong size of vector in ::fromString");
134  vx = m.get_unsafe(0, 0);
135  vy = m.get_unsafe(0, 1);
136  omega = DEG2RAD(m.get_unsafe(0, 2));
137 }
138 // Transform the (vx,vy) components for a counterclockwise rotation of `ang`
139 // radians
140 void TTwist2D::rotate(const double ang)
141 {
142  const double nvx = vx * cos(ang) - vy * sin(ang);
143  const double nvy = vx * sin(ang) + vy * cos(ang);
144  vx = nvx;
145  vy = nvy;
146 }
147 bool TTwist2D::operator==(const TTwist2D& o) const
148 {
149  return vx == o.vx && vy == o.vy && omega == o.omega;
150 }
151 bool TTwist2D::operator!=(const TTwist2D& o) const { return !(*this == o); }
153 {
154  return mrpt::math::TPose2D(vx * dt, vy * dt, omega * dt);
155 }
156 
157 // ----
159 {
160  s = mrpt::format(
161  "[%f %f %f %f %f %f]", vx, vy, vz, mrpt::utils::RAD2DEG(wx),
163 }
165 {
166  CMatrixDouble m;
167  if (!m.fromMatlabStringFormat(s))
168  THROW_EXCEPTION("Malformed expression in ::fromString");
169  ASSERTMSG_(
170  mrpt::math::size(m, 1) == 1 && mrpt::math::size(m, 2) == 6,
171  "Wrong size of vector in ::fromString");
172  for (int i = 0; i < 3; i++) (*this)[i] = m.get_unsafe(0, i);
173  for (int i = 0; i < 3; i++)
174  (*this)[3 + i] = DEG2RAD(m.get_unsafe(0, 3 + i));
175 }
176 // Transform all 6 components for a change of reference frame from "A" to
177 // another frame "B" whose rotation with respect to "A" is given by `rot`. The
178 // translational part of the pose is ignored
180 {
181  const TTwist3D t = *this;
183  vx = R(0, 0) * t.vx + R(0, 1) * t.vy + R(0, 2) * t.vz;
184  vy = R(1, 0) * t.vx + R(1, 1) * t.vy + R(1, 2) * t.vz;
185  vz = R(2, 0) * t.vx + R(2, 1) * t.vy + R(2, 2) * t.vz;
186 
187  wx = R(0, 0) * t.wx + R(0, 1) * t.wy + R(0, 2) * t.wz;
188  wy = R(1, 0) * t.wx + R(1, 1) * t.wy + R(1, 2) * t.wz;
189  wz = R(2, 0) * t.wx + R(2, 1) * t.wy + R(2, 2) * t.wz;
190 }
191 bool TTwist3D::operator==(const TTwist3D& o) const
192 {
193  return vx == o.vx && vy == o.vy && vz == o.vz && wx == o.wx && wy == o.wy &&
194  wz == o.wz;
195 }
196 bool TTwist3D::operator!=(const TTwist3D& o) const { return !(*this == o); }
197 TPoint3D::TPoint3D(const TPoint2D& p) : x(p.x), y(p.y), z(0.0) {}
198 TPoint3D::TPoint3D(const TPose2D& p) : x(p.x), y(p.y), z(0.0) {}
199 TPoint3D::TPoint3D(const TPose3D& p) : x(p.x), y(p.y), z(p.z) {}
201  : x(p.x()), y(p.y()), z(p.z())
202 {
203 }
205 {
206 }
207 bool TPoint3D::operator<(const TPoint3D& p) const
208 {
209  if (x < p.x)
210  return true;
211  else if (x > p.x)
212  return false;
213  else if (y < p.y)
214  return true;
215  else if (y > p.y)
216  return false;
217  else
218  return z < p.z;
219 }
221 {
222  CMatrixDouble m;
223  if (!m.fromMatlabStringFormat(s))
224  THROW_EXCEPTION("Malformed expression in ::fromString");
225  ASSERTMSG_(
226  mrpt::math::size(m, 1) == 1 && mrpt::math::size(m, 2) == 3,
227  "Wrong size of vector in ::fromString");
228  x = m.get_unsafe(0, 0);
229  y = m.get_unsafe(0, 1);
230  z = m.get_unsafe(0, 2);
231 }
232 
234  : x(p.x), y(p.y), z(0.0), yaw(0.0), pitch(0.0), roll(0.0)
235 {
236 }
238  : x(p.x), y(p.y), z(0.0), yaw(p.phi), pitch(0.0), roll(0.0)
239 {
240 }
242  : x(p.x), y(p.y), z(p.z), yaw(0.0), pitch(0.0), roll(0.0)
243 {
244 }
246  : x(p.x()),
247  y(p.y()),
248  z(p.z()),
249  yaw(p.yaw()),
250  pitch(p.pitch()),
251  roll(p.roll())
252 {
253 }
255 {
256  s = mrpt::format(
257  "[%f %f %f %f %f %f]", x, y, z, RAD2DEG(yaw), RAD2DEG(pitch),
258  RAD2DEG(roll));
259 }
263 {
264  // See:
265  // http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
266  const double cy = cos(yaw * 0.5), sy = sin(yaw * 0.5);
267  const double cp = cos(pitch * 0.5), sp = sin(pitch * 0.5);
268  const double cr = cos(roll * 0.5), sr = sin(roll * 0.5);
269 
270  const double ccc = cr * cp * cy;
271  const double ccs = cr * cp * sy;
272  const double css = cr * sp * sy;
273  const double sss = sr * sp * sy;
274  const double scc = sr * cp * cy;
275  const double ssc = sr * sp * cy;
276  const double csc = cr * sp * cy;
277  const double scs = sr * cp * sy;
278 
279  q[0] = ccc + sss;
280  q[1] = scc - css;
281  q[2] = csc + scs;
282  q[3] = ccs - ssc;
283 
284  // Compute 4x3 Jacobian: for details, see technical report:
285  // Parameterizations of SE(3) transformations: equivalences, compositions
286  // and uncertainty, J.L. Blanco (2010).
287  // http://www.mrpt.org/6D_poses:equivalences_compositions_and_uncertainty
288  if (out_dq_dr)
289  {
290  alignas(16) const double nums[4 * 3] = {
291  -0.5 * q[3], 0.5 * (-csc + scs), -0.5 * q[1],
292  -0.5 * q[2], 0.5 * (-ssc - ccs), 0.5 * q[0],
293  0.5 * q[1], 0.5 * (ccc - sss), 0.5 * q[3],
294  0.5 * q[0], 0.5 * (-css - scc), -0.5 * q[2]};
295  out_dq_dr->loadFromArray(nums);
296  }
297 }
299 {
300  CMatrixDouble m;
301  if (!m.fromMatlabStringFormat(s))
302  THROW_EXCEPTION("Malformed expression in ::fromString");
303  ASSERTMSG_(
304  mrpt::math::size(m, 1) == 1 && mrpt::math::size(m, 2) == 6,
305  "Wrong size of vector in ::fromString");
306  x = m.get_unsafe(0, 0);
307  y = m.get_unsafe(0, 1);
308  z = m.get_unsafe(0, 2);
309  yaw = DEG2RAD(m.get_unsafe(0, 3));
310  pitch = DEG2RAD(m.get_unsafe(0, 4));
311  roll = DEG2RAD(m.get_unsafe(0, 5));
312 }
313 
315  : x(p.x()),
316  y(p.y()),
317  z(p.z()),
318  qr(p.quat().r()),
319  qx(p.quat().x()),
320  qy(p.quat().y()),
321  qz(p.quat().z())
322 {
323 }
325 {
326  CMatrixDouble m;
327  if (!m.fromMatlabStringFormat(s))
328  THROW_EXCEPTION("Malformed expression in ::fromString");
329  ASSERTMSG_(
330  mrpt::math::size(m, 1) == 1 && mrpt::math::size(m, 2) == 7,
331  "Wrong size of vector in ::fromString");
332  for (size_t i = 0; i < m.getColCount(); i++)
333  (*this)[i] = m.get_unsafe(0, i);
334 }
335 
336 // Text streaming:
337 std::ostream& operator<<(std::ostream& o, const TPoint2D& p)
338 {
339  return (o << CPoint2D(p));
340 }
341 std::ostream& operator<<(std::ostream& o, const TPoint3D& p)
342 {
343  return (o << CPoint3D(p));
344 }
345 std::ostream& operator<<(std::ostream& o, const TPose2D& p)
346 {
347  return (o << CPose2D(p));
348 }
349 std::ostream& operator<<(std::ostream& o, const TPose3D& p)
350 {
351  return (o << CPose3D(p));
352 }
353 std::ostream& operator<<(std::ostream& o, const TPose3DQuat& p)
354 {
355  return (o << CPose3DQuat(p));
356 }
357 
359 {
360  return in >> s.point1 >> s.point2;
361 }
363 {
364  return out << s.point1 << s.point2;
365 }
367 {
368  return in >> l.coefs[0] >> l.coefs[1] >> l.coefs[2];
369 }
371 {
372  return out << l.coefs[0] << l.coefs[1] << l.coefs[2];
373 }
374 
377 {
378  return in >> s.point1 >> s.point2;
379 }
382 {
383  return out << s.point1 << s.point2;
384 }
387 {
388  return in >> l.pBase >> l.director[0] >> l.director[1] >> l.director[2];
389 }
392 {
393  return out << l.pBase << l.director[0] << l.director[1] << l.director[2];
394 }
397 {
398  return in >> p.coefs[0] >> p.coefs[1] >> p.coefs[2] >> p.coefs[3];
399 }
402 {
403  return out << p.coefs[0] << p.coefs[1] << p.coefs[2] << p.coefs[3];
404 }
405 
406 double TSegment2D::length() const { return math::distance(point1, point2); }
407 double TSegment2D::distance(const TPoint2D& point) const
408 {
409  return std::abs(signedDistance(point));
410 }
411 double TSegment2D::signedDistance(const TPoint2D& point) const
412 {
413  // It is reckoned whether the perpendicular line to the TSegment2D which
414  // passes through point crosses or not the referred segment,
415  // or what is the same, whether point makes an obtuse triangle with the
416  // segment or not (being the longest segment one between the point and
417  // either end of TSegment2D).
418  const double d1 = math::distance(point, point1);
419  if (point1 == point2) return d1;
420 
421  const double d2 = math::distance(point, point2);
422  const double d3 = length();
423  const double ds1 = square(d1);
424  const double ds2 = square(d2);
425  const double ds3 = square(d3);
426  if (ds1 > (ds2 + ds3) || ds2 > (ds1 + ds3))
427  // Fix sign:
428  return min(d1, d2) *
429  (TLine2D(*this).signedDistance(point) < 0 ? -1 : 1);
430  else
431  return TLine2D(*this).signedDistance(point);
432 }
433 bool TSegment2D::contains(const TPoint2D& point) const
434 {
435  return abs(math::distance(point1, point) + math::distance(point2, point) -
437 }
439 {
440  s = TSegment3D(*this);
441 }
443 {
444  point1 = TPoint2D(s.point1);
445  point2 = TPoint2D(s.point2);
446  if (point1 == point2)
447  throw std::logic_error("Segment is normal to projection plane");
448 }
449 
451 {
452  if (point1 < s.point1)
453  return true;
454  else if (s.point1 < point1)
455  return false;
456  else
457  return point2 < s.point2;
458 }
459 
460 double TSegment3D::length() const { return math::distance(point1, point2); }
461 double TSegment3D::distance(const TPoint3D& point) const
462 {
463  return min(
464  min(math::distance(point, point1), math::distance(point, point2)),
465  TLine3D(*this).distance(point));
466 }
467 double TSegment3D::distance(const TSegment3D& segment) const
468 {
469  Eigen::Vector3d u, v, w;
470  TPoint3D diff_vect = point2 - point1;
471  diff_vect.getAsVector(u);
472  diff_vect = segment.point2 - segment.point1;
473  diff_vect.getAsVector(v);
474  diff_vect = point1 - segment.point1;
475  diff_vect.getAsVector(w);
476  double a = u.dot(u); // always >= 0
477  double b = u.dot(v);
478  double c = v.dot(v); // always >= 0
479  double d = u.dot(w);
480  double e = v.dot(w);
481  double D = a * c - b * b; // always >= 0
482  double sc, sN, sD = D; // sc = sN / sD, default sD = D >= 0
483  double tc, tN, tD = D; // tc = tN / tD, default tD = D >= 0
484 
485  // compute the line parameters of the two closest points
486  if (D < 0.00000001)
487  { // the lines are almost parallel
488  sN = 0.0; // force using point P0 on segment S1
489  sD = 1.0; // to prevent possible division by 0.0 later
490  tN = e;
491  tD = c;
492  }
493  else
494  { // get the closest points on the infinite lines
495  sN = (b * e - c * d);
496  tN = (a * e - b * d);
497  if (sN < 0.0)
498  { // sc < 0 => the s=0 edge is visible
499  sN = 0.0;
500  tN = e;
501  tD = c;
502  }
503  else if (sN > sD)
504  { // sc > 1 => the s=1 edge is visible
505  sN = sD;
506  tN = e + b;
507  tD = c;
508  }
509  }
510 
511  if (tN < 0.0)
512  { // tc < 0 => the t=0 edge is visible
513  tN = 0.0;
514  // recompute sc for this edge
515  if (-d < 0.0)
516  sN = 0.0;
517  else if (-d > a)
518  sN = sD;
519  else
520  {
521  sN = -d;
522  sD = a;
523  }
524  }
525  else if (tN > tD)
526  { // tc > 1 => the t=1 edge is visible
527  tN = tD;
528  // recompute sc for this edge
529  if ((-d + b) < 0.0)
530  sN = 0;
531  else if ((-d + b) > a)
532  sN = sD;
533  else
534  {
535  sN = (-d + b);
536  sD = a;
537  }
538  }
539  // finally do the division to get sc and tc
540  sc = (fabs(sN) < 0.00000001 ? 0.0 : sN / sD);
541  tc = (fabs(tN) < 0.00000001 ? 0.0 : tN / tD);
542 
543  // get the difference of the two closest points
544  CVectorDouble dP = w + (sc * u) - (tc * v); // = S1(sc) - S2(tc)
545 
546  return dP.norm(); // return the closest distance
547 }
548 bool TSegment3D::contains(const TPoint3D& point) const
549 {
550  // Not very intuitive, but very fast, method.
551  return abs(math::distance(point1, point) + math::distance(point2, point) -
553 }
554 
556 {
557  if (point1 < s.point1)
558  return true;
559  else if (s.point1 < point1)
560  return false;
561  else
562  return point2 < s.point2;
563 }
564 
565 double TLine2D::evaluatePoint(const TPoint2D& point) const
566 {
567  return coefs[0] * point.x + coefs[1] * point.y + coefs[2];
568 }
569 bool TLine2D::contains(const TPoint2D& point) const
570 {
571  return abs(distance(point)) < getEpsilon();
572 }
573 double TLine2D::distance(const TPoint2D& point) const
574 {
575  return abs(evaluatePoint(point)) /
576  sqrt(coefs[0] * coefs[0] + coefs[1] * coefs[1]);
577 }
578 double TLine2D::signedDistance(const TPoint2D& point) const
579 {
580  return evaluatePoint(point) /
581  sqrt(coefs[0] * coefs[0] + coefs[1] * coefs[1]);
582 }
583 void TLine2D::getNormalVector(double (&vector)[2]) const
584 {
585  vector[0] = coefs[0];
586  vector[1] = coefs[1];
587 }
589 {
590  double s = sqrt(coefs[0] * coefs[0] + coefs[1] * coefs[1]);
591  for (size_t i = 0; i < 3; i++) coefs[i] /= s;
592 }
593 void TLine2D::getDirectorVector(double (&vector)[2]) const
594 {
595  vector[0] = -coefs[1];
596  vector[1] = coefs[0];
597 }
598 void TLine2D::generate3DObject(TLine3D& l) const { l = TLine3D(*this); }
600 {
601  // Line's director vector is (-coefs[1],coefs[0]).
602  // If line is horizontal, force x=0. Else, force y=0. In both cases, we'll
603  // find a suitable point.
604  outPose.phi(atan2(coefs[0], -coefs[1]));
605  if (abs(coefs[0]) < getEpsilon())
606  {
607  outPose.x(0);
608  outPose.y(-coefs[2] / coefs[1]);
609  }
610  else
611  {
612  outPose.x(-coefs[2] / coefs[0]);
613  outPose.y(0);
614  }
615 }
617  const TPoint2D& origin, mrpt::poses::CPose2D& outPose) const
618 {
619  if (!contains(origin))
620  throw std::logic_error("Base point is not contained in the line");
621  outPose = mrpt::poses::CPose2D(TPose2D(origin));
622  // Line's director vector is (-coefs[1],coefs[0]).
623  outPose.phi(atan2(coefs[0], -coefs[1]));
624 }
625 TLine2D::TLine2D(const TPoint2D& p1, const TPoint2D& p2)
626 {
627  if (p1 == p2) throw logic_error("Both points are the same");
628  coefs[0] = p2.y - p1.y;
629  coefs[1] = p1.x - p2.x;
630  coefs[2] = p2.x * p1.y - p2.y * p1.x;
631 }
633 {
634  coefs[0] = s.point2.y - s.point1.y;
635  coefs[1] = s.point1.x - s.point2.x;
636  coefs[2] = s.point2.x * s.point1.y - s.point2.y * s.point1.x;
637  // unitarize(); //¿?
638 }
640 {
641  // Line's projection to Z plane may be a point.
642  if (hypot(l.director[0], l.director[1]) < getEpsilon())
643  throw std::logic_error("Line is normal to projection plane");
644  coefs[0] = -l.director[1];
645  coefs[1] = l.director[0];
646  coefs[2] = l.pBase.x * l.director[1] - l.pBase.y * l.director[0];
647 }
648 
649 bool TLine3D::contains(const TPoint3D& point) const
650 {
651  double dx = point.x - pBase.x;
652  double dy = point.y - pBase.y;
653  double dz = point.z - pBase.z;
654  if (abs(dx) < getEpsilon() && abs(dy) < getEpsilon() &&
655  abs(dz) < getEpsilon())
656  return true;
657  // dx dy dz
658  // if -----------=-----------=-----------, point is inside the line.
659  // director[0] director[1] director[2]
660  return (abs(dx * director[1] - dy * director[0]) < getEpsilon()) &&
661  (abs(dx * director[2] - dz * director[0]) < getEpsilon()) &&
662  (abs(dy * director[2] - dz * director[1]) < getEpsilon());
663 }
664 double TLine3D::distance(const TPoint3D& point) const
665 {
666  // Let d be line's base point minus the argument. Then,
667  // d·director/(|d|·|director|) equals both vector's cosine.
668  // So, d·director/|director| equals d's projection over director. Then,
669  // distance is sqrt(|d|²-(d·director/|director|)²).
670  double d[3] = {point.x - pBase.x, point.y - pBase.y, point.z - pBase.z};
671  double dv = 0, d2 = 0, v2 = 0;
672  for (size_t i = 0; i < 3; i++)
673  {
674  dv += d[i] * director[i];
675  d2 += d[i] * d[i];
676  v2 += director[i] * director[i];
677  }
678  return sqrt(d2 - (dv * dv) / v2);
679 }
681 {
682  double s = sqrt(squareNorm<3, double>(director));
683  for (size_t i = 0; i < 3; i++) director[i] /= s;
684 }
685 TLine3D::TLine3D(const TPoint3D& p1, const TPoint3D& p2)
686 {
687  if (abs(math::distance(p1, p2)) < getEpsilon())
688  throw logic_error("Both points are the same");
689  pBase = p1;
690  director[0] = p2.x - p1.x;
691  director[1] = p2.y - p1.y;
692  director[2] = p2.z - p1.z;
693 }
695 {
696  pBase = s.point1;
697  director[0] = s.point2.x - s.point1.x;
698  director[1] = s.point2.y - s.point1.y;
699  director[2] = s.point2.z - s.point1.z;
700 }
702 {
703  director[0] = -l.coefs[1];
704  director[1] = l.coefs[0];
705  director[2] = 0;
706  // We assume that either l.coefs[0] or l.coefs[1] is not null. Respectively,
707  // either y or x can be used as free cordinate.
708  if (abs(l.coefs[0]) >= getEpsilon())
709  {
710  pBase.x = -l.coefs[2] / l.coefs[0];
711  pBase.y = 0;
712  }
713  else
714  {
715  pBase.x = 0;
716  pBase.y = -l.coefs[1] / l.coefs[0];
717  }
718  pBase.z = 0;
719 }
720 
721 double TPlane::evaluatePoint(const TPoint3D& point) const
722 {
723  return dotProduct<3, double>(coefs, point) + coefs[3];
724 }
725 bool TPlane::contains(const TPoint3D& point) const
726 {
727  return distance(point) < getEpsilon();
728 }
729 bool TPlane::contains(const TLine3D& line) const
730 {
731  if (!contains(line.pBase)) return false; // Base point must be contained
732  return abs(getAngle(*this, line)) <
733  getEpsilon(); // Plane's normal must be normal to director vector
734 }
735 double TPlane::distance(const TPoint3D& point) const
736 {
737  return abs(evaluatePoint(point)) / sqrt(squareNorm<3, double>(coefs));
738 }
739 double TPlane::distance(const TLine3D& line) const
740 {
741  if (abs(getAngle(*this, line)) >= getEpsilon())
742  return 0; // Plane crosses with line
743  else
744  return distance(line.pBase);
745 }
746 void TPlane::getNormalVector(double (&vector)[3]) const
747 {
748  vector[0] = coefs[0];
749  vector[1] = coefs[1];
750  vector[2] = coefs[2];
751 }
753 {
754  double s = sqrt(squareNorm<3, double>(coefs));
755  for (size_t i = 0; i < 4; i++) coefs[i] /= s;
756 }
757 
758 // Returns a 6D pose such as its XY plane coincides with the plane
760 {
761  double normal[3];
762  getUnitaryNormalVector(normal);
763  CMatrixDouble AXIS;
764  generateAxisBaseFromDirectionAndAxis(normal, 2, AXIS);
765  for (size_t i = 0; i < 3; i++)
766  if (abs(coefs[i]) >= getEpsilon())
767  {
768  AXIS.set_unsafe(i, 3, -coefs[3] / coefs[i]);
769  break;
770  }
771  outPose = mrpt::poses::CPose3D(AXIS);
772 }
774  const TPoint3D& newOrigin, mrpt::poses::CPose3D& pose)
775 {
776  if (!contains(newOrigin))
777  throw std::logic_error("Base point is not in the plane.");
778  double normal[3];
779  getUnitaryNormalVector(normal);
780  CMatrixDouble AXIS;
781  generateAxisBaseFromDirectionAndAxis(normal, 2, AXIS);
782  for (size_t i = 0; i < 3; i++) AXIS.set_unsafe(i, 3, newOrigin[i]);
783  pose = mrpt::poses::CPose3D(AXIS);
784 }
785 TPlane::TPlane(const TPoint3D& p1, const TPoint3D& p2, const TPoint3D& p3)
786 {
787  double dx1 = p2.x - p1.x;
788  double dy1 = p2.y - p1.y;
789  double dz1 = p2.z - p1.z;
790  double dx2 = p3.x - p1.x;
791  double dy2 = p3.y - p1.y;
792  double dz2 = p3.z - p1.z;
793  coefs[0] = dy1 * dz2 - dy2 * dz1;
794  coefs[1] = dz1 * dx2 - dz2 * dx1;
795  coefs[2] = dx1 * dy2 - dx2 * dy1;
796  if (abs(coefs[0]) < getEpsilon() && abs(coefs[1]) < getEpsilon() &&
797  abs(coefs[2]) < getEpsilon())
798  throw logic_error("Points are linearly dependent");
799  coefs[3] = -coefs[0] * p1.x - coefs[1] * p1.y - coefs[2] * p1.z;
800 }
801 TPlane::TPlane(const TPoint3D& p1, const TLine3D& r2)
802 {
803  double dx1 = p1.x - r2.pBase.x;
804  double dy1 = p1.y - r2.pBase.y;
805  double dz1 = p1.z - r2.pBase.z;
806  coefs[0] = dy1 * r2.director[2] - dz1 * r2.director[1];
807  coefs[1] = dz1 * r2.director[0] - dx1 * r2.director[2];
808  coefs[2] = dx1 * r2.director[1] - dy1 * r2.director[0];
809  if (abs(coefs[0]) < getEpsilon() && abs(coefs[1]) < getEpsilon() &&
810  abs(coefs[2]) < getEpsilon())
811  throw logic_error("Point is contained in the line");
812  coefs[3] = -coefs[0] * p1.x - coefs[1] * p1.y - coefs[2] * p1.z;
813 }
814 TPlane::TPlane(const TLine3D& r1, const TLine3D& r2)
815 {
817  coefs[3] =
818  -coefs[0] * r1.pBase.x - coefs[1] * r1.pBase.y - coefs[2] * r1.pBase.z;
819  if (abs(coefs[0]) < getEpsilon() && abs(coefs[1]) < getEpsilon() &&
820  abs(coefs[2]) < getEpsilon())
821  {
822  // Lines are parallel
823  if (r1.contains(r2.pBase)) throw std::logic_error("Lines are the same");
824  // Use a line's director vector and both pBase's difference to create
825  // the plane.
826  double d[3];
827  for (size_t i = 0; i < 3; i++) d[i] = r1.pBase[i] - r2.pBase[i];
828  crossProduct3D(r1.director, d, coefs);
829  coefs[3] = -coefs[0] * r1.pBase.x - coefs[1] * r1.pBase.y -
830  coefs[2] * r1.pBase.z;
831  }
832  else if (abs(evaluatePoint(r2.pBase)) >= getEpsilon())
833  throw logic_error("Lines do not intersect");
834 }
835 
836 template <class T>
837 inline void removeUnusedVertices(T& poly)
838 {
839  size_t N = poly.size();
840  if (N < 3) return;
841  std::vector<size_t> unused;
842  if (abs(mrpt::math::distance(poly[N - 1], poly[0]) +
843  mrpt::math::distance(poly[0], poly[1]) -
844  mrpt::math::distance(poly[N - 1], poly[1])) <
846  unused.push_back(0);
847  for (size_t i = 1; i < N - 1; i++)
848  if (abs(mrpt::math::distance(poly[i - 1], poly[i]) +
849  mrpt::math::distance(poly[i], poly[i + 1]) -
850  mrpt::math::distance(poly[i - 1], poly[i + 1])) <
852  unused.push_back(i);
853  if (abs(mrpt::math::distance(poly[N - 2], poly[N - 1]) +
854  mrpt::math::distance(poly[N - 1], poly[0]) -
855  mrpt::math::distance(poly[N - 2], poly[0])) <
857  unused.push_back(N - 1);
858  unused.push_back(N);
859  size_t diff = 1;
860  for (size_t i = 0; i < unused.size() - 1; i++)
861  {
862  size_t last = unused[i + 1];
863  for (size_t j = unused[i] + 1 - diff; j < last - diff; j++)
864  poly[j] = poly[j + diff];
865  }
866  poly.resize(N + 1 - unused.size());
867 }
868 template <class T>
869 inline void removeRepVertices(T& poly)
870 {
871  size_t N = poly.size();
872  if (N < 3) return;
873  std::vector<size_t> rep;
874  for (size_t i = 0; i < N - 1; i++)
875  if (mrpt::math::distance(poly[i], poly[i + 1]) < getEpsilon())
876  rep.push_back(i);
877  if (mrpt::math::distance(poly[N - 1], poly[0]) < getEpsilon())
878  rep.push_back(N - 1);
879  rep.push_back(N);
880  size_t diff = 1;
881  for (size_t i = 0; i < rep.size() - 1; i++)
882  {
883  size_t last = rep[i + 1];
884  for (size_t j = rep[i] + 1 - diff; j < last - diff; j++)
885  poly[j] = poly[j + diff];
886  }
887  poly.resize(N + 1 - rep.size());
888 }
889 
890 double TPolygon2D::distance(const TPoint2D& point) const
891 {
892  if (contains(point)) return 0;
893  std::vector<TSegment2D> sgs;
894  getAsSegmentList(sgs);
895 
896  if (sgs.empty())
897  THROW_EXCEPTION("Cannot compute distance to an empty polygon.")
898 
899  double distance = std::numeric_limits<double>::max();
900 
901  for (vector<TSegment2D>::const_iterator it = sgs.begin(); it != sgs.end();
902  ++it)
903  {
904  double d = (*it).distance(point);
905  if (d < distance) distance = d;
906  }
907  return distance;
908 }
909 
911  TPoint2D& min_coords, TPoint2D& max_coords) const
912 {
913  ASSERTMSG_(!this->empty(), "getBoundingBox() called on an empty polygon!");
914  min_coords.x = min_coords.y = std::numeric_limits<double>::max();
915  max_coords.x = max_coords.y = -std::numeric_limits<double>::max();
916  for (size_t i = 0; i < size(); i++)
917  {
918  mrpt::utils::keep_min(min_coords.x, (*this)[i].x);
919  mrpt::utils::keep_min(min_coords.y, (*this)[i].y);
920  mrpt::utils::keep_max(max_coords.x, (*this)[i].x);
921  mrpt::utils::keep_max(max_coords.y, (*this)[i].y);
922  }
923 }
924 
925 // isLeft(): tests if a point is Left|On|Right of an infinite line.
926 // Input: three points P0, P1, and P2
927 // Return: >0 for P2 left of the line through P0 and P1
928 // =0 for P2 on the line
929 // <0 for P2 right of the line
930 // See: Algorithm 1 "Area of Triangles and Polygons"
931 inline double isLeft(
932  const mrpt::math::TPoint2D& P0, const mrpt::math::TPoint2D& P1,
933  const mrpt::math::TPoint2D& P2)
934 {
935  return ((P1.x - P0.x) * (P2.y - P0.y) - (P2.x - P0.x) * (P1.y - P0.y));
936 }
937 
938 bool TPolygon2D::contains(const TPoint2D& P) const
939 {
940  int wn = 0; // the winding number counter
941 
942  // loop through all edges of the polygon
943  const size_t n = this->size();
944  for (size_t i = 0; i < n; i++) // edge from V[i] to V[i+1]
945  {
946  if ((*this)[i].y <= P.y)
947  {
948  // start y <= P.y
949  if ((*this)[(i + 1) % n].y > P.y) // an upward crossing
950  if (isLeft((*this)[i], (*this)[(i + 1) % n], P) >
951  0) // P left of edge
952  ++wn; // have a valid up intersect
953  }
954  else
955  {
956  // start y > P.y (no test needed)
957  if ((*this)[(i + 1) % n].y <= P.y) // a downward crossing
958  if (isLeft((*this)[i], (*this)[(i + 1) % n], P) <
959  0) // P right of edge
960  --wn; // have a valid down intersect
961  }
962  }
963 
964  return wn != 0;
965 }
966 void TPolygon2D::getAsSegmentList(vector<TSegment2D>& v) const
967 {
968  size_t N = size();
969  v.resize(N);
970  for (size_t i = 0; i < N - 1; i++)
971  v[i] = TSegment2D(operator[](i), operator[](i + 1));
972  v[N - 1] = TSegment2D(operator[](N - 1), operator[](0));
973 }
974 
976 {
977  p = TPolygon3D(*this);
978 }
979 // Auxiliar functor class to compute polygon's center
980 template <class T, int N>
982 {
983  public:
984  T& object;
985  FAddPoint(T& o) : object(o)
986  {
987  for (size_t i = 0; i < N; i++) object[i] = 0.0;
988  }
989  void operator()(const T& o)
990  {
991  for (size_t i = 0; i < N; i++) object[i] += o[i];
992  }
993 };
995 {
996  for_each(begin(), end(), FAddPoint<TPoint2D, 2>(p));
997  size_t N = size();
998  p.x /= N;
999  p.y /= N;
1000 }
1002 {
1003  size_t N = size();
1004  if (N <= 3) return true;
1005  vector<TSegment2D> sgms;
1006  getAsSegmentList(sgms);
1007  for (size_t i = 0; i < N; i++)
1008  {
1009  char s = 0;
1010  TLine2D l = TLine2D(sgms[i]);
1011  for (size_t j = 0; j < N; j++)
1012  {
1013  double d = l.evaluatePoint(operator[](j));
1014  if (abs(d) < getEpsilon())
1015  continue;
1016  else if (!s)
1017  s = (d > 0) ? 1 : -1;
1018  else if (s != ((d > 0) ? 1 : -1))
1019  return false;
1020  }
1021  }
1022  return true;
1023 }
1026 {
1028  removeUnusedVertices(*this);
1029 }
1031  std::vector<double>& x, std::vector<double>& y) const
1032 {
1033  size_t N = size();
1034  x.resize(N + 1);
1035  y.resize(N + 1);
1036  for (size_t i = 0; i < N; i++)
1037  {
1038  x[i] = operator[](i).x;
1039  y[i] = operator[](i).y;
1040  }
1041  x[N] = operator[](0).x;
1042  y[N] = operator[](0).y;
1043 }
1045 {
1046  size_t N = p.size();
1047  resize(N);
1048  for (size_t i = 0; i < N; i++) operator[](i) = TPoint2D(p[i]);
1049 }
1051  size_t numEdges, double radius, TPolygon2D& poly)
1052 {
1053  if (numEdges < 3 || abs(radius) < getEpsilon())
1054  throw std::logic_error(
1055  "Invalid arguments for regular polygon creations");
1056  poly.resize(numEdges);
1057  for (size_t i = 0; i < numEdges; i++)
1058  {
1059  double angle = i * M_PI * 2 / numEdges;
1060  poly[i] = TPoint2D(radius * cos(angle), radius * sin(angle));
1061  }
1062 }
1064  size_t numEdges, double radius, TPolygon2D& poly,
1065  const mrpt::poses::CPose2D& pose)
1066 {
1067  createRegularPolygon(numEdges, radius, poly);
1068  for (size_t i = 0; i < numEdges; i++) poly[i] = pose + poly[i];
1069 }
1070 
1071 double TPolygon3D::distance(const TPoint3D& point) const
1072 {
1073  TPlane pl;
1074  if (!getPlane(pl))
1075  throw std::logic_error("Polygon does not conform a plane");
1076  TPoint3D newPoint;
1077  TPolygon3D newPoly;
1078  mrpt::poses::CPose3D pose;
1079  pl.getAsPose3DForcingOrigin(operator[](0), pose);
1080  project3D(point, pose, newPoint);
1081  project3D(*this, pose, newPoly);
1082  double distance2D = TPolygon2D(newPoly).distance(TPoint2D(newPoint));
1083  return sqrt(newPoint.z * newPoint.z + distance2D * distance2D);
1084 }
1085 bool TPolygon3D::contains(const TPoint3D& point) const
1086 {
1087  TPoint3D pMin, pMax;
1088  getPrismBounds(*this, pMin, pMax);
1089  if (point.x + getEpsilon() < pMin.x ||
1090  point.y + getEpsilon() < pMin.y ||
1091  point.z + getEpsilon() < pMin.z ||
1092  point.x > pMax.x + getEpsilon() ||
1093  point.y > pMax.y + getEpsilon() ||
1094  point.z > pMax.z + getEpsilon())
1095  return false;
1096  TPlane plane;
1097  if (!getPlane(plane))
1098  throw std::logic_error("Polygon does not conform a plane");
1099  TPolygon3D projectedPoly;
1100  TPoint3D projectedPoint;
1101  mrpt::poses::CPose3D pose;
1102  // plane.getAsPose3DForcingOrigin(operator[](0),pose);
1103  plane.getAsPose3D(pose);
1104  pose = mrpt::poses::CPose3D(0, 0, 0, 0, 0, 0) - pose;
1105  project3D(point, pose, projectedPoint);
1106  if (abs(projectedPoint.z) >= getEpsilon())
1107  return false; // Point is not inside the polygon's plane.
1108  project3D(*this, pose, projectedPoly);
1109  return TPolygon2D(projectedPoly).contains(TPoint2D(projectedPoint));
1110 }
1111 void TPolygon3D::getAsSegmentList(vector<TSegment3D>& v) const
1112 {
1113  size_t N = size();
1114  v.resize(N);
1115  for (size_t i = 0; i < N - 1; i++)
1116  v[i] = TSegment3D(operator[](i), operator[](i + 1));
1117  v[N - 1] = TSegment3D(operator[](N - 1), operator[](0));
1118 }
1119 bool TPolygon3D::getPlane(TPlane& p) const { return conformAPlane(*this, p); }
1121 {
1122  getRegressionPlane(*this, p);
1123 }
1125 {
1126  for_each(begin(), end(), FAddPoint<TPoint3D, 3>(p));
1127  size_t N = size();
1128  p.x /= N;
1129  p.y /= N;
1130  p.z /= N;
1131 }
1132 bool TPolygon3D::isSkew() const { return !mrpt::math::conformAPlane(*this); }
1135 {
1137  removeUnusedVertices(*this);
1138 }
1140 {
1141  size_t N = p.size();
1142  resize(N);
1143  for (size_t i = 0; i < N; i++) operator[](i) = p[i];
1144 }
1146  size_t numEdges, double radius, TPolygon3D& poly)
1147 {
1148  if (numEdges < 3 || abs(radius) < getEpsilon())
1149  throw std::logic_error(
1150  "Invalid arguments for regular polygon creations");
1151  poly.resize(numEdges);
1152  for (size_t i = 0; i < numEdges; i++)
1153  {
1154  double angle = i * 2 * M_PI / numEdges;
1155  poly[i] = TPoint3D(radius * cos(angle), radius * sin(angle), 0);
1156  }
1157 }
1159  size_t numEdges, double radius, TPolygon3D& poly,
1160  const mrpt::poses::CPose3D& pose)
1161 {
1162  createRegularPolygon(numEdges, radius, poly);
1163  for (size_t i = 0; i < numEdges; i++)
1164  pose.composePoint(
1165  poly[i][0], poly[i][1], poly[i][2], poly[i][0], poly[i][1],
1166  poly[i][2]);
1167 }
1168 
1170 {
1171  switch (type)
1172  {
1173  case GEOMETRIC_TYPE_POINT:
1174  obj = TPoint3D(data.point);
1175  break;
1177  obj = TSegment3D(data.segment);
1178  break;
1179  case GEOMETRIC_TYPE_LINE:
1180  obj = TLine3D(data.line);
1181  break;
1183  obj = TPolygon3D(*(data.polygon));
1184  break;
1185  default:
1186  obj = TObject3D();
1187  break;
1188  }
1189 }
1191  const std::vector<TObject2D>& objs, std::vector<TPoint2D>& pnts)
1192 {
1193  for (vector<TObject2D>::const_iterator it = objs.begin(); it != objs.end();
1194  ++it)
1195  if (it->isPoint()) pnts.push_back(it->data.point);
1196 }
1198  const std::vector<TObject2D>& objs, std::vector<TSegment2D>& sgms)
1199 {
1200  for (vector<TObject2D>::const_iterator it = objs.begin(); it != objs.end();
1201  ++it)
1202  if (it->isSegment()) sgms.push_back(it->data.segment);
1203 }
1205  const std::vector<TObject2D>& objs, std::vector<TLine2D>& lins)
1206 {
1207  for (vector<TObject2D>::const_iterator it = objs.begin(); it != objs.end();
1208  ++it)
1209  if (it->isLine()) lins.push_back(it->data.line);
1210 }
1212  const std::vector<TObject2D>& objs, std::vector<TPolygon2D>& polys)
1213 {
1214  for (vector<TObject2D>::const_iterator it = objs.begin(); it != objs.end();
1215  ++it)
1216  if (it->isPolygon()) polys.push_back(*(it->data.polygon));
1217 }
1219  const std::vector<TObject2D>& objs, std::vector<TPoint2D>& pnts,
1220  std::vector<TObject2D>& remainder)
1221 {
1222  for (vector<TObject2D>::const_iterator it = objs.begin(); it != objs.end();
1223  ++it)
1224  if (it->isPoint())
1225  pnts.push_back(it->data.point);
1226  else
1227  remainder.push_back(*it);
1228 }
1230  const std::vector<TObject2D>& objs, std::vector<TSegment2D>& sgms,
1231  std::vector<TObject2D>& remainder)
1232 {
1233  for (vector<TObject2D>::const_iterator it = objs.begin(); it != objs.end();
1234  ++it)
1235  if (it->isSegment())
1236  sgms.push_back(it->data.segment);
1237  else
1238  remainder.push_back(*it);
1239 }
1241  const std::vector<TObject2D>& objs, std::vector<TLine2D>& lins,
1242  std::vector<TObject2D>& remainder)
1243 {
1244  for (vector<TObject2D>::const_iterator it = objs.begin(); it != objs.end();
1245  ++it)
1246  if (it->isLine())
1247  lins.push_back(it->data.line);
1248  else
1249  remainder.push_back(*it);
1250 }
1252  const std::vector<TObject2D>& objs, std::vector<TPolygon2D>& polys,
1253  vector<TObject2D>& remainder)
1254 {
1255  for (vector<TObject2D>::const_iterator it = objs.begin(); it != objs.end();
1256  ++it)
1257  if (it->isPolygon())
1258  polys.push_back(*(it->data.polygon));
1259  else
1260  remainder.push_back(*it);
1261 }
1263  const std::vector<TObject3D>& objs, std::vector<TPoint3D>& pnts)
1264 {
1265  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1266  ++it)
1267  if (it->isPoint()) pnts.push_back(it->data.point);
1268 }
1270  const std::vector<TObject3D>& objs, std::vector<TSegment3D>& sgms)
1271 {
1272  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1273  ++it)
1274  if (it->isSegment()) sgms.push_back(it->data.segment);
1275 }
1277  const std::vector<TObject3D>& objs, std::vector<TLine3D>& lins)
1278 {
1279  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1280  ++it)
1281  if (it->isLine()) lins.push_back(it->data.line);
1282 }
1284  const std::vector<TObject3D>& objs, std::vector<TPlane>& plns)
1285 {
1286  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1287  ++it)
1288  if (it->isPlane()) plns.push_back(it->data.plane);
1289 }
1291  const std::vector<TObject3D>& objs, std::vector<TPolygon3D>& polys)
1292 {
1293  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1294  ++it)
1295  if (it->isPolygon()) polys.push_back(*(it->data.polygon));
1296 }
1298  const std::vector<TObject3D>& objs, std::vector<TPoint3D>& pnts,
1299  std::vector<TObject3D>& remainder)
1300 {
1301  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1302  ++it)
1303  if (it->isPoint())
1304  pnts.push_back(it->data.point);
1305  else
1306  remainder.push_back(*it);
1307 }
1309  const std::vector<TObject3D>& objs, std::vector<TSegment3D>& sgms,
1310  std::vector<TObject3D>& remainder)
1311 {
1312  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1313  ++it)
1314  if (it->isSegment())
1315  sgms.push_back(it->data.segment);
1316  else
1317  remainder.push_back(*it);
1318 }
1320  const std::vector<TObject3D>& objs, std::vector<TLine3D>& lins,
1321  std::vector<TObject3D>& remainder)
1322 {
1323  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1324  ++it)
1325  if (it->isLine())
1326  lins.push_back(it->data.line);
1327  else
1328  remainder.push_back(*it);
1329 }
1331  const std::vector<TObject3D>& objs, std::vector<TPlane>& plns,
1332  std::vector<TObject3D>& remainder)
1333 {
1334  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1335  ++it)
1336  if (it->isPlane())
1337  plns.push_back(it->data.plane);
1338  else
1339  remainder.push_back(*it);
1340 }
1342  const std::vector<TObject3D>& objs, std::vector<TPolygon3D>& polys,
1343  vector<TObject3D>& remainder)
1344 {
1345  for (vector<TObject3D>::const_iterator it = objs.begin(); it != objs.end();
1346  ++it)
1347  if (it->isPolygon())
1348  polys.push_back(*(it->data.polygon));
1349  else
1350  remainder.push_back(*it);
1351 }
1352 
1355 {
1356  in >> o.x >> o.y;
1357  return in;
1358 }
1361 {
1362  out << o.x << o.y;
1363  return out;
1364 }
1365 
1368 {
1369  in >> o.x >> o.y >> o.z;
1370  return in;
1371 }
1374 {
1375  out << o.x << o.y << o.z;
1376  return out;
1377 }
1378 
1381 {
1382  in >> o.x >> o.y >> o.phi;
1383  return in;
1384 }
1387 {
1388  out << o.x << o.y << o.phi;
1389  return out;
1390 }
1391 
1394 {
1395  for (unsigned int i = 0; i < o.size(); i++) in >> o[i];
1396  return in;
1397 }
1400 {
1401  for (unsigned int i = 0; i < o.size(); i++) out << o[i];
1402  return out;
1403 }
1404 
1407 {
1408  for (unsigned int i = 0; i < o.size(); i++) in >> o[i];
1409  return in;
1410 }
1413 {
1414  for (unsigned int i = 0; i < o.size(); i++) out << o[i];
1415  return out;
1416 }
1417 
1422 
1427 
1430 {
1431  in >> o.x >> o.y >> o.z >> o.yaw >> o.pitch >> o.roll;
1432  return in;
1433 }
1436 {
1437  out << o.x << o.y << o.z << o.yaw << o.pitch << o.roll;
1438  return out;
1439 }
1440 
1443 {
1444  uint16_t type;
1445  in >> type;
1446  switch (static_cast<unsigned char>(type))
1447  {
1448  case GEOMETRIC_TYPE_POINT:
1449  {
1450  TPoint2D p;
1451  in >> p;
1452  o = p;
1453  }
1454  break;
1456  {
1457  TSegment2D s;
1458  in >> s;
1459  o = s;
1460  }
1461  break;
1462  case GEOMETRIC_TYPE_LINE:
1463  {
1464  TLine2D l;
1465  in >> l;
1466  o = l;
1467  }
1468  break;
1470  {
1471  TPolygon2D p;
1472  in >> p;
1473  o = p;
1474  }
1475  break;
1477  {
1478  o = TObject2D();
1479  }
1480  break;
1481  default:
1482  throw std::logic_error(
1483  "Unknown TObject2D type found while reading stream");
1484  }
1485  return in;
1486 }
1489 {
1490  out << static_cast<uint16_t>(o.getType());
1491  switch (o.getType())
1492  {
1493  case GEOMETRIC_TYPE_POINT:
1494  {
1495  TPoint2D p;
1496  o.getPoint(p);
1497  return out << p;
1498  };
1500  {
1501  TSegment2D s;
1502  o.getSegment(s);
1503  return out << s;
1504  };
1505  case GEOMETRIC_TYPE_LINE:
1506  {
1507  TLine2D l;
1508  o.getLine(l);
1509  return out << l;
1510  };
1512  {
1513  TPolygon2D p;
1514  o.getPolygon(p);
1515  return out << p;
1516  };
1517  }
1518  return out;
1519 }
1520 
1523 {
1524  uint16_t type;
1525  in >> type;
1526  switch (static_cast<unsigned char>(type))
1527  {
1528  case GEOMETRIC_TYPE_POINT:
1529  {
1530  TPoint3D p;
1531  in >> p;
1532  o = p;
1533  }
1534  break;
1536  {
1537  TSegment3D s;
1538  in >> s;
1539  o = s;
1540  }
1541  break;
1542  case GEOMETRIC_TYPE_LINE:
1543  {
1544  TLine3D l;
1545  in >> l;
1546  o = l;
1547  }
1548  break;
1549  case GEOMETRIC_TYPE_PLANE:
1550  {
1551  TPlane p;
1552  in >> p;
1553  o = p;
1554  }
1555  break;
1557  {
1558  TPolygon3D p;
1559  in >> p;
1560  o = p;
1561  }
1562  break;
1564  {
1565  o = TObject3D();
1566  }
1567  break;
1568  default:
1569  throw std::logic_error(
1570  "Unknown TObject3D type found while reading stream");
1571  }
1572  return in;
1573 }
1576 {
1577  out << static_cast<uint16_t>(o.getType());
1578  switch (o.getType())
1579  {
1580  case GEOMETRIC_TYPE_POINT:
1581  {
1582  TPoint3D p;
1583  o.getPoint(p);
1584  return out << p;
1585  };
1587  {
1588  TSegment3D s;
1589  o.getSegment(s);
1590  return out << s;
1591  };
1592  case GEOMETRIC_TYPE_LINE:
1593  {
1594  TLine3D l;
1595  o.getLine(l);
1596  return out << l;
1597  };
1598  case GEOMETRIC_TYPE_PLANE:
1599  {
1600  TPlane p;
1601  o.getPlane(p);
1602  return out << p;
1603  };
1605  {
1606  TPolygon3D p;
1607  o.getPolygon(p);
1608  return out << p;
1609  };
1610  }
1611  return out;
1612 }
1613 }
1614 } // end of namespaces
const float R
#define RAD2DEG
Definition: bits.h:115
#define M_PI
Definition: bits.h:92
#define DEG2RAD
Definition: bits.h:112
A quaternion, which can represent a 3D rotation as pair , with a real part "r" and a 3D vector ,...
Definition: CQuaternion.h:47
2D polygon, inheriting from std::vector<TPoint2D>.
TPolygon2D()
Default constructor
double distance(const TPoint2D &point) const
Distance to a point (always >=0)
void getAsSegmentList(std::vector< TSegment2D > &v) const
Gets as set of segments, instead of points.
void getCenter(TPoint2D &p) const
Polygon's central point.
static void createRegularPolygon(size_t numEdges, double radius, TPolygon2D &poly)
Static method to create a regular polygon, given its size and radius.
void generate3DObject(TPolygon3D &p) const
Projects into 3D space, zeroing the z.
bool isConvex() const
Checks whether is convex.
void removeRedundantVertices()
Erase every redundant vertex from the polygon, saving space.
void removeRepeatedVertices()
Erase repeated vertices.
bool contains(const TPoint2D &point) const
Check whether a point is inside (or within geometryEpsilon of a polygon edge).
void getPlotData(std::vector< double > &x, std::vector< double > &y) const
Gets plot data, ready to use on a 2D plot.
void getBoundingBox(TPoint2D &min_coords, TPoint2D &max_coords) const
Get polygon bounding box.
3D polygon, inheriting from std::vector<TPoint3D>
TPolygon3D()
Default constructor.
void getBestFittingPlane(TPlane &p) const
Gets the best fitting plane, disregarding whether the polygon actually fits inside or not.
void getAsSegmentList(std::vector< TSegment3D > &v) const
Gets as set of segments, instead of set of points.
bool isSkew() const
Check whether the polygon is skew.
bool contains(const TPoint3D &point) const
Check whether a point is inside (or within geometryEpsilon of a polygon edge).
static void createRegularPolygon(size_t numEdges, double radius, TPolygon3D &poly)
Static method to create a regular polygon, given its size and radius.
void removeRedundantVertices()
Erase every redundant vertex, thus saving space.
double distance(const TPoint3D &point) const
Distance to point (always >=0)
void removeRepeatedVertices()
Remove polygon's repeated vertices.
bool getPlane(TPlane &p) const
Gets a plane which contains the polygon.
void getCenter(TPoint3D &p) const
Get polygon's central point.
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction.
Definition: types_math.h:70
A class used to store a 2D point.
Definition: CPoint2D.h:37
A class used to store a 3D point.
Definition: CPoint3D.h:33
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle.
Definition: CPose2D.h:41
const double & phi() const
Get the phi angle of the 2D pose (in radians)
Definition: CPose2D.h:91
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:89
void getRotationMatrix(mrpt::math::CMatrixDouble33 &ROT) const
Get the 3x3 rotation matrix.
Definition: CPose3D.h:237
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
A class used to store a 3D pose as a translation (x,y,z) and a quaternion (qr,qx,qy,...
Definition: CPose3DQuat.h:49
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:135
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:42
EIGEN_STRONG_INLINE bool empty() const
const Scalar * const_iterator
Definition: eigen_plugins.h:27
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:29
GLdouble GLdouble t
Definition: glext.h:3689
GLenum GLsizei n
Definition: glext.h:5074
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
const GLdouble * v
Definition: glext.h:3678
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
const GLubyte * c
Definition: glext.h:6313
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3547
GLuint GLuint end
Definition: glext.h:3528
const GLfloat * tc
Definition: glext.h:6362
GLenum GLint GLint y
Definition: glext.h:3538
GLubyte GLubyte b
Definition: glext.h:6279
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3528
GLuint in
Definition: glext.h:7274
GLenum GLint x
Definition: glext.h:3538
GLfloat GLfloat GLfloat v2
Definition: glext.h:4107
GLfloat GLfloat p
Definition: glext.h:6305
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
GLdouble GLdouble z
Definition: glext.h:3872
GLdouble s
Definition: glext.h:3676
GLsizei const GLchar ** string
Definition: glext.h:4101
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:3721
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:53
const unsigned char GEOMETRIC_TYPE_POINT
Object type identifier for TPoint2D or TPoint3D.
const unsigned char GEOMETRIC_TYPE_LINE
Object type identifier for TLine2D or TLine3D.
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
Definition: geometry.cpp:1885
const unsigned char GEOMETRIC_TYPE_UNDEFINED
Object type identifier for empty TObject2D or TObject3D.
void project3D(const TPoint3D &point, const mrpt::poses::CPose3D &newXYpose, TPoint3D &newPoint)
Uses the given pose 3D to project a point into a new base.
Definition: geometry.h:333
std::ostream & operator<<(std::ostream &o, const TPoint2D &p)
const unsigned char GEOMETRIC_TYPE_POLYGON
Object type identifier for TPolygon2D or TPolygon3D.
void getPrismBounds(const std::vector< TPoint3D > &poly, TPoint3D &pMin, TPoint3D &pMax)
Gets the prism bounds of a 3D polygon or set of 3D points.
Definition: geometry.cpp:2015
const unsigned char GEOMETRIC_TYPE_SEGMENT
Object type identifier for TSegment2D or TSegment3D.
double getEpsilon()
Gets the value of the geometric epsilon (default = 1e-5)
Definition: geometry.cpp:30
bool conformAPlane(const std::vector< TPoint3D > &points)
Checks whether this polygon or set of points acceptably fits a plane.
Definition: geometry.cpp:995
void generateAxisBaseFromDirectionAndAxis(const double(&vec)[3], char coord, CMatrixDouble &matrix)
Creates a homogeneus matrix (4x4) such that the coordinate given (0 for x, 1 for y,...
Definition: geometry.cpp:2073
void crossProduct3D(const T &v0, const U &v1, V &vOut)
Computes the cross product of two 3D vectors, returning a vector normal to both.
Definition: geometry.h:822
double getRegressionPlane(const std::vector< TPoint3D > &points, TPlane &plane)
Using eigenvalues, gets the best fitting plane for a set of 3D points.
Definition: geometry.cpp:2157
double getAngle(const TPlane &p1, const TPlane &p2)
Computes the angle between two planes.
Definition: geometry.cpp:863
const unsigned char GEOMETRIC_TYPE_PLANE
Object type identifier for TPlane.
#define THROW_EXCEPTION(msg)
Definition: mrpt_macros.h:111
#define ASSERTMSG_(f, __ERROR_MSG)
Definition: mrpt_macros.h:306
TPoint2D lightFromPose(const mrpt::poses::CPoint2D &p)
Convert a pose into a light-weight structure (functional form, needed for forward declarations)
size_t size(const MATRIXLIKE &m, const int dim)
Definition: bits.h:41
void removeRepVertices(T &poly)
mrpt::utils::CStream & operator>>(mrpt::utils::CStream &in, CMatrix::Ptr &pObj)
void removeUnusedVertices(T &poly)
double isLeft(const mrpt::math::TPoint2D &P0, const mrpt::math::TPoint2D &P1, const mrpt::math::TPoint2D &P2)
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
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,...
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value.
Definition: bits.h:227
double RAD2DEG(const double x)
Radians to degrees.
Definition: bits.h:102
VALUE & operator[](const KEY &key)
Write/read via [i] operator, that creates an element if it didn't exist already.
Definition: ts_hash_map.h:200
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value.
Definition: bits.h:220
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
This file implements several operations that operate element-wise on individual or pairs of container...
#define min(a, b)
unsigned __int16 uint16_t
Definition: rptypes.h:44
2D line without bounds, represented by its equation .
TLine2D()
Fast default constructor.
double evaluatePoint(const TPoint2D &point) const
Evaluate point in the line's equation.
void generate3DObject(TLine3D &l) const
Project into 3D space, setting the z to 0.
void getNormalVector(double(&vector)[2]) const
Get line's normal vector.
double signedDistance(const TPoint2D &point) const
Distance with sign from a given point (sign indicates side).
double coefs[3]
Line coefficients, stored as an array: .
void unitarize()
Unitarize line's normal vector.
double distance(const TPoint2D &point) const
Distance from a given point.
void getDirectorVector(double(&vector)[2]) const
Get line's director vector.
void getAsPose2D(mrpt::poses::CPose2D &outPose) const
Get a pose2D whose X axis corresponds to the line.
bool contains(const TPoint2D &point) const
Check whether a point is inside the line.
void getAsPose2DForcingOrigin(const TPoint2D &origin, mrpt::poses::CPose2D &outPose) const
Get a pose2D whose X axis corresponds to the line, forcing the base point to one given.
3D line, represented by a base point and a director vector.
TLine3D()
Fast default constructor.
double distance(const TPoint3D &point) const
Distance between the line and a point.
double director[3]
Director vector.
void unitarize()
Unitarize director vector.
bool contains(const TPoint3D &point) const
Check whether a point is inside the line.
TPoint3D pBase
Base point.
Standard type for storing any lightweight 2D type.
void generate3DObject(TObject3D &obj) const
Project into 3D space.
static void getLines(const std::vector< TObject2D > &objs, std::vector< TLine2D > &lins)
Static method to retrieve all the lines in a vector of TObject2D.
static void getPoints(const std::vector< TObject2D > &objs, std::vector< TPoint2D > &pnts)
Static method to retrieve all the points in a vector of TObject2D.
bool getLine(TLine2D &r) const
Gets the content as a line, returning false if the type is inadequate.
unsigned char getType() const
Gets content type.
bool getSegment(TSegment2D &s) const
Gets the content as a segment, returning false if the type is inadequate.
bool getPolygon(TPolygon2D &p) const
Gets the content as a polygon, returning false if the type is inadequate.
bool getPoint(TPoint2D &p) const
Gets the content as a point, returning false if the type is inadequate.
static void getSegments(const std::vector< TObject2D > &objs, std::vector< TSegment2D > &sgms)
Static method to retrieve all the segments in a vector of TObject2D.
static void getPolygons(const std::vector< TObject2D > &objs, std::vector< TPolygon2D > &polys)
Static method to retrieve all the polygons in a vector of TObject2D.
Standard object for storing any 3D lightweight object.
static void getSegments(const std::vector< TObject3D > &objs, std::vector< TSegment3D > &sgms)
Static method to retrieve every segment included in a vector of objects.
bool getPlane(TPlane &p) const
Gets the content as a plane, returning false if the type is not adequate.
unsigned char getType() const
Gets object type.
static void getPoints(const std::vector< TObject3D > &objs, std::vector< TPoint3D > &pnts)
Static method to retrieve every point included in a vector of objects.
bool getSegment(TSegment3D &s) const
Gets the content as a segment, returning false if the type is not adequate.
bool getLine(TLine3D &r) const
Gets the content as a line, returning false if the type is not adequate.
static void getLines(const std::vector< TObject3D > &objs, std::vector< TLine3D > &lins)
Static method to retrieve every line included in a vector of objects.
static void getPolygons(const std::vector< TObject3D > &objs, std::vector< TPolygon3D > &polys)
Static method to retrieve every polygon included in a vector of objects.
bool getPoint(TPoint3D &p) const
Gets the content as a point, returning false if the type is not adequate.
static void getPlanes(const std::vector< TObject3D > &objs, std::vector< TPlane > &plns)
Static method to retrieve every plane included in a vector of objects.
bool getPolygon(TPolygon3D &p) const
Gets the content as a polygon, returning false if the type is not adequate.
3D Plane, represented by its equation
TPlane()
Fast default constructor.
double distance(const TPoint3D &point) const
Distance to 3D point.
double evaluatePoint(const TPoint3D &point) const
Evaluate a point in the plane's equation.
void getNormalVector(double(&vec)[3]) const
Get plane's normal vector.
void getUnitaryNormalVector(double(&vec)[3])
Unitarize, then get normal vector.
void getAsPose3D(mrpt::poses::CPose3D &outPose)
Gets a pose whose XY plane corresponds to this plane.
bool contains(const TPoint3D &point) const
Check whether a point is contained into the plane.
void getAsPose3DForcingOrigin(const TPoint3D &newOrigin, mrpt::poses::CPose3D &pose)
Gets a pose whose XY plane corresponds to this, forcing an exact point as its spatial coordinates.
double coefs[4]
Plane coefficients, stored as an array: .
void unitarize()
Unitarize normal vector.
Lightweight 2D point.
double x
X,Y coordinates.
void fromString(const std::string &s)
Set the current object value from a string generated by 'asString' (eg: "[0.02 1.04]" )
bool operator<(const TPoint2D &p) const
TPoint2D()
Default fast constructor.
Lightweight 3D point.
double x
X,Y,Z coordinates.
void fromString(const std::string &s)
Set the current object value from a string generated by 'asString' (eg: "[0.02 1.04 -0....
TPoint3D()
Default fast constructor.
void getAsVector(VECTORLIKE &v) const
Transformation into vector.
bool operator<(const TPoint3D &p) const
Lightweight 2D pose.
double phi
Orientation (rads)
mrpt::math::TPose2D operator+(const mrpt::math::TPose2D &b) const
Operator "oplus" pose composition: "ret=this \oplus b".
double x
X,Y coordinates.
std::string asString() const
void fromString(const std::string &s)
Set the current object value from a string generated by 'asString' (eg: "[0.02 1.04 -45....
TPose2D()
Default fast constructor.
mrpt::math::TPose2D operator-(const mrpt::math::TPose2D &b) const
Operator "ominus" pose composition: "ret=this \ominus b".
Lightweight 3D pose (three spatial coordinates, plus three angular coordinates).
void fromString(const std::string &s)
Set the current object value from a string generated by 'asString' (eg: "[0.02 1.04 -0....
void getAsQuaternion(mrpt::math::CQuaternion< double > &q, mrpt::math::CMatrixFixedNumeric< double, 4, 3 > *out_dq_dr=NULL) const
Returns the quaternion associated to the rotation of this object (NOTE: XYZ translation is ignored)
double x
X,Y,Z, coords.
double roll
Roll coordinate (rotation angle over X coordinate).
std::string asString() const
TPose3D()
Default fast constructor.
double pitch
Pitch coordinate (rotation angle over Y axis).
double yaw
Yaw coordinate (rotation angle over Z axis).
Lightweight 3D pose (three spatial coordinates, plus a quaternion ).
void fromString(const std::string &s)
Set the current object value from a string generated by 'asString' (eg: "[0.02 1.04 -0....
TPose3DQuat()
Default fast constructor.
2D segment, consisting of two points.
bool contains(const TPoint2D &point) const
Check whether a point is inside a segment.
TPoint2D point2
Destiny point.
double signedDistance(const TPoint2D &point) const
Distance with sign to point (sign indicates which side the point is).
bool operator<(const TSegment2D &s) const
TSegment2D()
Fast default constructor.
TPoint2D point1
Origin point.
void generate3DObject(TSegment3D &s) const
Project into 3D space, setting the z to 0.
double length() const
Segment length.
double distance(const TPoint2D &point) const
Distance to point.
3D segment, consisting of two points.
double distance(const TPoint3D &point) const
Distance to point.
TPoint3D point1
Origin point.
double length() const
Segment length.
TPoint3D point2
Destiny point.
bool operator<(const TSegment3D &s) const
bool contains(const TPoint3D &point) const
Check whether a point is inside the segment.
2D twist: 2D velocity vector (vx,vy) + planar angular velocity (omega)
std::string asString() const
void rotate(const double ang)
Transform the (vx,vy) components for a counterclockwise rotation of ang radians.
bool operator!=(const TTwist2D &o) const
mrpt::math::TPose2D operator*(const double dt) const
Returns the pose increment of multiplying each twist component times "dt" seconds.
void fromString(const std::string &s)
Set the current object value from a string generated by 'asString' (eg: "[0.02 1.04 -45....
bool operator==(const TTwist2D &o) const
double vx
Velocity components: X,Y (m/s)
double omega
Angular velocity (rad/s)
3D twist: 3D velocity vector (vx,vy,vz) + angular velocity (wx,wy,wz)
void fromString(const std::string &s)
Set the current object value from a string generated by 'asString' (eg: "[vx vy vz wx wy wz]" )
std::string asString() const
bool operator!=(const TTwist3D &o) const
void rotate(const mrpt::poses::CPose3D &rot)
Transform all 6 components for a change of reference frame from "A" to another frame "B" whose rotati...
double vx
Velocity components: X,Y (m/s)
bool operator==(const TTwist3D &o) const
double wx
Angular velocity (rad/s)



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