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 unsigned char GEOMETRIC_TYPE_PLANE
Object type identifier for TPlane.
static void getSegments(const std::vector< TObject2D > &objs, std::vector< TSegment2D > &sgms)
Static method to retrieve all the segments in a vector of TObject2D.
bool getPoint(TPoint2D &p) const
Gets the content as a point, returning false if the type is inadequate.
double x() const
Common members of all points & poses classes.
Definition: CPoseOrPoint.h:135
static void createRegularPolygon(size_t numEdges, double radius, TPolygon3D &poly)
Static method to create a regular polygon, given its size and radius.
static void createRegularPolygon(size_t numEdges, double radius, TPolygon2D &poly)
Static method to create a regular polygon, given its size and radius.
void fromString(const std::string &s)
Set the current object value from a string generated by &#39;asString&#39; (eg: "[0.02 1.04]" ) ...
bool getPolygon(TPolygon2D &p) const
Gets the content as a polygon, returning false if the type is inadequate.
void rotate(const double ang)
Transform the (vx,vy) components for a counterclockwise rotation of ang radians.
EIGEN_STRONG_INLINE bool empty() const
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
GLdouble GLdouble t
Definition: glext.h:3689
const unsigned char GEOMETRIC_TYPE_LINE
Object type identifier for TLine2D or TLine3D.
GLdouble GLdouble z
Definition: glext.h:3872
#define min(a, b)
unsigned __int16 uint16_t
Definition: rptypes.h:44
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, 2 for z) corresponds to the provided vector.
Definition: geometry.cpp:2073
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
unsigned char getType() const
Gets content type.
TPoint2D lightFromPose(const mrpt::poses::CPoint2D &p)
Convert a pose into a light-weight structure (functional form, needed for forward declarations) ...
double x
X,Y coordinates.
const unsigned char GEOMETRIC_TYPE_POINT
Object type identifier for TPoint2D or TPoint3D.
bool operator==(const TTwist3D &o) const
double x
X,Y coordinates.
double distance(const TPoint3D &point) const
Distance between the line and a point.
void getPlotData(std::vector< double > &x, std::vector< double > &y) const
Gets plot data, ready to use on a 2D plot.
size_t size(const MATRIXLIKE &m, const int dim)
Definition: bits.h:41
bool isSkew() const
Check whether the polygon is skew.
TLine2D()
Fast default constructor.
bool getSegment(TSegment3D &s) const
Gets the content as a segment, returning false if the type is not adequate.
bool contains(const TPoint2D &point) const
Check whether a point is inside a segment.
double roll
Roll coordinate (rotation angle over X coordinate).
static void getPolygons(const std::vector< TObject2D > &objs, std::vector< TPolygon2D > &polys)
Static method to retrieve all the polygons in a vector of TObject2D.
TPolygon3D()
Default constructor.
#define THROW_EXCEPTION(msg)
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:3721
GLenum GLsizei n
Definition: glext.h:5074
double distance(const TPoint2D &point) const
Distance to point.
static void getLines(const std::vector< TObject2D > &objs, std::vector< TLine2D > &lins)
Static method to retrieve all the lines in a vector of TObject2D.
This file implements several operations that operate element-wise on individual or pairs of container...
double x
X,Y,Z, coords.
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) ...
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:29
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:42
TPoint3D()
Default fast constructor.
double signedDistance(const TPoint2D &point) const
Distance with sign from a given point (sign indicates side).
Standard type for storing any lightweight 2D type.
TLine3D()
Fast default constructor.
bool getLine(TLine2D &r) const
Gets the content as a line, returning false if the type is inadequate.
void getAsPose3D(mrpt::poses::CPose3D &outPose)
Gets a pose whose XY plane corresponds to this plane.
void getAsSegmentList(std::vector< TSegment2D > &v) const
Gets as set of segments, instead of points.
bool getPlane(TPlane &p) const
Gets the content as a plane, returning false if the type is not adequate.
TPoint3D pBase
Base point.
Standard object for storing any 3D lightweight object.
STL namespace.
bool getSegment(TSegment2D &s) const
Gets the content as a segment, returning false if the type is inadequate.
bool contains(const TPoint2D &point) const
Check whether a point is inside the line.
#define M_PI
Definition: bits.h:92
void removeRepeatedVertices()
Erase repeated vertices.
double signedDistance(const TPoint2D &point) const
Distance with sign to point (sign indicates which side the point is).
const Scalar * const_iterator
Definition: eigen_plugins.h:27
void generate3DObject(TLine3D &l) const
Project into 3D space, setting the z to 0.
void removeRepVertices(T &poly)
void fromString(const std::string &s)
Set the current object value from a string generated by &#39;asString&#39; (eg: "[0.02 1.04 -45...
double distance(const TPoint3D &point) const
Distance to 3D point.
double yaw
Yaw coordinate (rotation angle over Z axis).
GLdouble s
Definition: glext.h:3676
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
void fromString(const std::string &s)
Set the current object value from a string generated by &#39;asString&#39; (eg: "[vx vy vz wx wy wz]" ) ...
bool operator<(const TSegment3D &s) const
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...
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
3D twist: 3D velocity vector (vx,vy,vz) + angular velocity (wx,wy,wz)
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:811
TPoint3D point1
Origin point.
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
bool conformAPlane(const std::vector< TPoint3D > &points)
Checks whether this polygon or set of points acceptably fits a plane.
Definition: geometry.cpp:995
static void getSegments(const std::vector< TObject3D > &objs, std::vector< TSegment3D > &sgms)
Static method to retrieve every segment included in a vector of objects.
TPose3D()
Default fast constructor.
2D twist: 2D velocity vector (vx,vy) + planar angular velocity (omega)
void getNormalVector(double(&vector)[2]) const
Get line&#39;s normal vector.
void generate3DObject(TPolygon3D &p) const
Projects into 3D space, zeroing the z.
bool contains(const TPoint3D &point) const
Check whether a point is inside the line.
double isLeft(const mrpt::math::TPoint2D &P0, const mrpt::math::TPoint2D &P1, const mrpt::math::TPoint2D &P2)
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
void unitarize()
Unitarize line&#39;s normal vector.
std::string asString() const
void getBoundingBox(TPoint2D &min_coords, TPoint2D &max_coords) const
Get polygon bounding box.
bool getPolygon(TPolygon3D &p) const
Gets the content as a polygon, returning false if the type is not adequate.
2D segment, consisting of two points.
double distance(const TPoint3D &point) const
Distance to point.
void fromString(const std::string &s)
Set the current object value from a string generated by &#39;asString&#39; (eg: "[0.02 1.04 -45...
double RAD2DEG(const double x)
Radians to degrees.
const GLfloat * tc
Definition: glext.h:6362
3D segment, consisting of two points.
double length() const
Segment length.
TPoint3D point2
Destiny point.
bool operator<(const TSegment2D &s) const
std::ostream & operator<<(std::ostream &o, const TPoint2D &p)
const GLubyte * c
Definition: glext.h:6313
double vx
Velocity components: X,Y (m/s)
mrpt::math::TPose2D operator+(const mrpt::math::TPose2D &b) const
Operator "oplus" pose composition: "ret=this \oplus b".
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...
static void getLines(const std::vector< TObject3D > &objs, std::vector< TLine3D > &lins)
Static method to retrieve every line included in a vector of objects.
void unitarize()
Unitarize normal vector.
mrpt::math::TPose2D operator*(const double dt) const
Returns the pose increment of multiplying each twist component times "dt" seconds.
GLuint GLuint end
Definition: glext.h:3528
const unsigned char GEOMETRIC_TYPE_SEGMENT
Object type identifier for TSegment2D or TSegment3D.
VALUE & operator[](const KEY &key)
Write/read via [i] operator, that creates an element if it didn&#39;t exist already.
Definition: ts_hash_map.h:200
static void getPolygons(const std::vector< TObject3D > &objs, std::vector< TPolygon3D > &polys)
Static method to retrieve every polygon included in a vector of objects.
3D Plane, represented by its equation
bool getPlane(TPlane &p) const
Gets a plane which contains the polygon.
GLubyte GLubyte b
Definition: glext.h:6279
double coefs[3]
Line coefficients, stored as an array: .
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
TPolygon2D()
Default constructor.
double x
X,Y,Z coordinates.
void removeRedundantVertices()
Erase every redundant vertex, thus saving space.
TPose3DQuat()
Default fast constructor.
TPoint2D point2
Destiny point.
A class used to store a 3D pose as a translation (x,y,z) and a quaternion (qr,qx,qy,qz).
Definition: CPose3DQuat.h:48
#define DEG2RAD
void getCenter(TPoint2D &p) const
Polygon&#39;s central point.
double getAngle(const TPlane &p1, const TPlane &p2)
Computes the angle between two planes.
Definition: geometry.cpp:863
GLsizei const GLchar ** string
Definition: glext.h:4101
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
Definition: wrap2pi.h:53
A class used to store a 2D point.
Definition: CPoint2D.h:36
A class used to store a 3D point.
Definition: CPoint3D.h:32
void unitarize()
Unitarize director vector.
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
Definition: CPoint.h:17
bool contains(const TPoint3D &point) const
Check whether a point is inside (or within geometryEpsilon of a polygon edge).
bool getPoint(TPoint3D &p) const
Gets the content as a point, returning false if the type is not adequate.
double pitch
Pitch coordinate (rotation angle over Y axis).
Lightweight 3D pose (three spatial coordinates, plus a quaternion ).
double distance(const TPoint3D &point) const
Distance to point (always >=0)
double director[3]
Director vector.
TPoint2D point1
Origin point.
bool isConvex() const
Checks whether is convex.
TPoint2D()
Default fast constructor.
mrpt::utils::CStream & operator>>(mrpt::utils::CStream &in, CMatrix::Ptr &pObj)
void generate3DObject(TSegment3D &s) const
Project into 3D space, setting the z to 0.
bool contains(const TPoint2D &point) const
Check whether a point is inside (or within geometryEpsilon of a polygon edge).
void removeUnusedVertices(T &poly)
double distance(const TPoint2D &point) const
Distance to a point (always >=0)
void getAsPose2D(mrpt::poses::CPose2D &outPose) const
Get a pose2D whose X axis corresponds to the line.
#define RAD2DEG
const GLdouble * v
Definition: glext.h:3678
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
TPlane()
Fast default constructor.
double wx
Angular velocity (rad/s)
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
size_t size(const MATRIXLIKE &m, const int dim)
double vx
Velocity components: X,Y (m/s)
void generate3DObject(TObject3D &obj) const
Project into 3D space.
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
Definition: CPose2D.h:40
const float R
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
Definition: CPose3D.h:88
static void getPoints(const std::vector< TObject2D > &objs, std::vector< TPoint2D > &pnts)
Static method to retrieve all the points in a vector of TObject2D.
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
void getUnitaryNormalVector(double(&vec)[3])
Unitarize, then get normal vector.
double coefs[4]
Plane coefficients, stored as an array: .
void composePoint(double lx, double ly, double lz, double &gx, double &gy, double &gz, mrpt::math::CMatrixFixedNumeric< double, 3, 3 > *out_jacobian_df_dpoint=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dpose=nullptr, mrpt::math::CMatrixFixedNumeric< double, 3, 6 > *out_jacobian_df_dse3=nullptr, bool use_small_rot_approx=false) const
An alternative, slightly more efficient way of doing with G and L being 3D points and P this 6D pose...
Definition: CPose3D.cpp:453
TSegment2D()
Fast default constructor.
const double & phi() const
Get the phi angle of the 2D pose (in radians)
Definition: CPose2D.h:91
void fromString(const std::string &s)
Set the current object value from a string generated by &#39;asString&#39; (eg: "[0.02 1.04 -0...
bool operator!=(const TTwist3D &o) const
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:329
Lightweight 3D pose (three spatial coordinates, plus three angular coordinates).
GLuint in
Definition: glext.h:7274
Lightweight 2D pose.
void removeRedundantVertices()
Erase every redundant vertex from the polygon, saving space.
void removeRepeatedVertices()
Remove polygon&#39;s repeated vertices.
bool contains(const TPoint3D &point) const
Check whether a point is inside the segment.
bool getLine(TLine3D &r) const
Gets the content as a line, returning false if the type is not adequate.
double evaluatePoint(const TPoint3D &point) const
Evaluate a point in the plane&#39;s equation.
std::string asString() const
void fromString(const std::string &s)
Set the current object value from a string generated by &#39;asString&#39; (eg: "[0.02 1.04 -0...
bool operator<(const TPoint3D &p) const
double evaluatePoint(const TPoint2D &point) const
Evaluate point in the line&#39;s equation.
GLenum GLint GLint y
Definition: glext.h:3538
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.
TPose2D()
Default fast constructor.
GLfloat GLfloat GLfloat v2
Definition: glext.h:4107
unsigned char getType() const
Gets object type.
const unsigned char GEOMETRIC_TYPE_UNDEFINED
Object type identifier for empty TObject2D or TObject3D.
mrpt::math::TPose2D operator-(const mrpt::math::TPose2D &b) const
Operator "ominus" pose composition: "ret=this \ominus b".
GLenum GLint x
Definition: glext.h:3538
A quaternion, which can represent a 3D rotation as pair , with a real part "r" and a 3D vector ...
Definition: CQuaternion.h:46
void getRotationMatrix(mrpt::math::CMatrixDouble33 &ROT) const
Get the 3x3 rotation matrix.
Definition: CPose3D.h:237
Lightweight 3D point.
double distance(const TPoint2D &point) const
Distance from a given point.
void getAsSegmentList(std::vector< TSegment3D > &v) const
Gets as set of segments, instead of set of points.
void getBestFittingPlane(TPlane &p) const
Gets the best fitting plane, disregarding whether the polygon actually fits inside or not...
void getDirectorVector(double(&vector)[2]) const
Get line&#39;s director vector.
double getEpsilon()
Gets the value of the geometric epsilon (default = 1e-5)
Definition: geometry.cpp:30
std::string asString() const
Lightweight 2D point.
const unsigned char GEOMETRIC_TYPE_POLYGON
Object type identifier for TPolygon2D or TPolygon3D.
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...
#define ASSERTMSG_(f, __ERROR_MSG)
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:3546
std::string asString() const
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
GLfloat GLfloat p
Definition: glext.h:6305
static void getPlanes(const std::vector< TObject3D > &objs, std::vector< TPlane > &plns)
Static method to retrieve every plane included in a vector of objects.
double phi
Orientation (rads)
bool operator<(const TPoint2D &p) const
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3528
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...
void getAsVector(VECTORLIKE &v) const
Transformation into vector.
2D polygon, inheriting from std::vector<TPoint2D>.
3D polygon, inheriting from std::vector<TPoint3D>
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
Definition: geometry.cpp:1885
void getCenter(TPoint3D &p) const
Get polygon&#39;s central point.
double omega
Angular velocity (rad/s)
bool contains(const TPoint3D &point) const
Check whether a point is contained into the plane.
double length() const
Segment length.
bool operator!=(const TTwist2D &o) const
void fromString(const std::string &s)
Set the current object value from a string generated by &#39;asString&#39; (eg: "[0.02 1.04 -0...
bool operator==(const TTwist2D &o) const
void getNormalVector(double(&vec)[3]) const
Get plane&#39;s normal vector.
3D line, represented by a base point and a director vector.
2D line without bounds, represented by its equation .
static void getPoints(const std::vector< TObject3D > &objs, std::vector< TPoint3D > &pnts)
Static method to retrieve every point included in a vector of objects.



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