MRSL DecompUtil Library  0.1
An implementaion of convex decomposition over point cloud
geometric_utils.h
Go to the documentation of this file.
1 
5 #ifndef DECOMP_GEOMETRIC_UTILS_H
6 #define DECOMP_GEOMETRIC_UTILS_H
7 
8 #include <iostream>
10 #include <Eigen/Eigenvalues>
11 
13 template <int Dim>
15  Eigen::SelfAdjointEigenSolver<Matf<Dim, Dim>> es(A);
16  return es.eigenvalues();
17 }
18 
20 inline Mat2f vec2_to_rotation(const Vec2f &v) {
21  decimal_t yaw = std::atan2(v(1), v(0));
22  Mat2f R;
23  R << cos(yaw), -sin(yaw),
24  sin(yaw), cos(yaw);
25  return R;
26 }
27 
28 inline Mat3f vec3_to_rotation(const Vec3f &v) {
29  // zero roll
30  Vec3f rpy(0, std::atan2(-v(2), v.topRows<2>().norm()),
31  std::atan2(v(1), v(0)));
32  Quatf qx(cos(rpy(0) / 2), sin(rpy(0) / 2), 0, 0);
33  Quatf qy(cos(rpy(1) / 2), 0, sin(rpy(1) / 2), 0);
34  Quatf qz(cos(rpy(2) / 2), 0, 0, sin(rpy(2) / 2));
35  return Mat3f(qz * qy * qx);
36 }
37 
39 inline vec_Vec2f sort_pts(const vec_Vec2f &pts) {
41  if(pts.empty())
42  return pts;
44  Vec2f avg = Vec2f::Zero();
45  for (const auto& pt : pts)
46  avg += pt;
47  avg /= pts.size();
48 
51  pts_valued.resize(pts.size());
52  for (unsigned int i = 0; i < pts.size(); i++) {
53  decimal_t theta = atan2(pts[i](1) - avg(1), pts[i](0) - avg(0));
54  pts_valued[i] = std::make_pair(theta, pts[i]);
55  }
56 
57  std::sort(pts_valued.begin(), pts_valued.end(),
58  [](const std::pair<decimal_t, Vec2f> &i,
59  const std::pair<decimal_t, Vec2f> &j) {
60  return i.first < j.first;});
61  vec_Vec2f pts_sorted(pts_valued.size());
62  for (size_t i = 0; i < pts_valued.size(); i++)
63  pts_sorted[i] = pts_valued[i].second;
64  return pts_sorted;
65 }
66 
67 
69 inline bool line_intersect(const std::pair<Vec2f, Vec2f> &v1,
70  const std::pair<Vec2f, Vec2f> &v2,
71  Vec2f &pi) {
72  decimal_t a1 = -v1.first(1);
73  decimal_t b1 = v1.first(0);
74  decimal_t c1 = a1 * v1.second(0) + b1 * v1.second(1);
75 
76  decimal_t a2 = -v2.first(1);
77  decimal_t b2 = v2.first(0);
78  decimal_t c2 = a2 * v2.second(0) + b2 * v2.second(1);
79 
80  decimal_t x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1);
81  decimal_t y = (c1 * a2 - c2 * a1) / (a2 * b1 - a1 * b2);
82 
83  if (std::isnan(x) || std::isnan(y) || std::isinf(x) || std::isinf(y))
84  return false;
85  else {
86  pi << x, y;
87  return true;
88  }
89 }
90 
91 
92 
94 inline vec_Vec2f line_intersects(const vec_E<std::pair<Vec2f, Vec2f>> &lines) {
95  vec_Vec2f pts;
96  for (unsigned int i = 0; i < lines.size(); i++) {
97  for (unsigned int j = i + 1; j < lines.size(); j++) {
98  Vec2f pi;
99  if (line_intersect(lines[i], lines[j], pi)) {
100  pts.push_back(pi);
101  }
102  }
103  }
104  return pts;
105 }
106 
107 
108 inline vec_Vec2f cal_vertices(const Polyhedron2D &poly) {
110  const auto vs = poly.hyperplanes();
111  for (unsigned int i = 0; i < vs.size(); i++) {
112  Vec2f n = vs[i].n_;
113  Vec2f v(-n(1), n(0));
114  v = v.normalized();
115 
116  lines.push_back(std::make_pair(v, vs[i].p_));
117  /*
118  std::cout << "add p: " << lines.back().second.transpose() <<
119  " v: " << lines.back().first.transpose() << std::endl;
120  */
121  }
122 
123  auto vts = line_intersects(lines);
124  //for(const auto& it: vts)
125  //std::cout << "vertice: " << it.transpose() << std::endl;
126 
127  vec_Vec2f vts_inside = poly.points_inside(vts);
128  vts_inside = sort_pts(vts_inside);
129 
130  return vts_inside;
131 }
132 
135  vec_E<vec_Vec3f> bds;
136  const auto vts = poly.hyperplanes();
137  //**** for each plane, find lines on it
138  for (unsigned int i = 0; i < vts.size(); i++) {
139  const Vec3f t = vts[i].p_;
140  const Vec3f n = vts[i].n_;
141  const Quatf q = Quatf::FromTwoVectors(Vec3f(0, 0, 1), n);
142  const Mat3f R(q); // body to world
144  for (unsigned int j = 0; j < vts.size(); j++) {
145  if (j == i)
146  continue;
147  Vec3f nw = vts[j].n_;
148  Vec3f nb = R.transpose() * nw;
149  decimal_t bb = vts[j].p_.dot(nw) - nw.dot(t);
150  Vec2f v = Vec3f(0, 0, 1).cross(nb).topRows<2>(); // line direction
151  Vec2f p; // point on the line
152  if (nb(1) != 0)
153  p << 0, bb / nb(1);
154  else if (nb(0) != 0)
155  p << bb / nb(0), 0;
156  else
157  continue;
158  lines.push_back(std::make_pair(v, p));
159  }
160 
161  //**** find all intersect points
162  vec_Vec2f pts = line_intersects(lines);
163  //**** filter out points inside polytope
164  vec_Vec2f pts_inside;
165  for (const auto& it : pts) {
166  Vec3f p = R * Vec3f(it(0), it(1), 0) + t; // convert to world frame
167  if (poly.inside(p))
168  pts_inside.push_back(it);
169  }
170 
171  if(pts_inside.size() > 2) {
172  //**** sort in plane frame
173  pts_inside = sort_pts(pts_inside);
174 
175  //**** transform to world frame
176  vec_Vec3f points_valid;
177  for (auto &it : pts_inside)
178  points_valid.push_back(R * Vec3f(it(0), it(1), 0) + t);
179 
180  //**** insert resulting polygon
181  bds.push_back(points_valid);
182  }
183  }
184  return bds;
185 }
186 
187 
188 #endif
Matf< 3, 3 > Mat3f
3x3 Matrix in float
Definition: data_type.h:99
bool inside(const Vecf< Dim > &pt) const
Check if the point is inside polyhedron, non-exclusive.
Definition: polyhedron.h:54
Provide a few widely used function for basic type.
Polyhedron class.
Definition: polyhedron.h:41
Mat2f vec2_to_rotation(const Vec2f &v)
Calculate rotation matrix from a vector (aligned with x-axis)
Definition: geometric_utils.h:20
vec_Vec2f sort_pts(const vec_Vec2f &pts)
Sort points on the same plane in the counter-clockwise order.
Definition: geometric_utils.h:39
vec_Vecf< Dim > points_inside(const vec_Vecf< Dim > &O) const
Calculate points inside polyhedron, non-exclusive.
Definition: polyhedron.h:65
vec_E< Hyperplane< Dim > > hyperplanes() const
Get the hyperplane array.
Definition: polyhedron.h:83
Vecf< 3 > Vec3f
Eigen 1D float vector of size 3.
Definition: data_type.h:79
Matf< 2, 2 > Mat2f
2x2 Matrix in float
Definition: data_type.h:97
Eigen::Matrix< decimal_t, M, N > Matf
MxN Eigen matrix.
Definition: data_type.h:63
bool line_intersect(const std::pair< Vec2f, Vec2f > &v1, const std::pair< Vec2f, Vec2f > &v2, Vec2f &pi)
Find intersection between two lines on the same plane, return false if they are not intersected...
Definition: geometric_utils.h:69
double decimal_t
Rename the float type used in lib.
Definition: data_type.h:50
std::vector< T, Eigen::aligned_allocator< T >> vec_E
Pre-allocated std::vector for Eigen using vec_E.
Definition: data_type.h:54
vec_E< vec_Vec3f > cal_vertices(const Polyhedron3D &poly)
Find extreme points of Polyhedron3D.
Definition: geometric_utils.h:134
Vecf< 2 > Vec2f
Eigen 1D float vector of size 2.
Definition: data_type.h:75
Eigen::Quaternion< decimal_t > Quatf
Allias of Eigen::Quaterniond.
Definition: data_type.h:120
Eigen::Matrix< decimal_t, N, 1 > Vecf
Eigen 1D float vector.
Definition: data_type.h:57
vec_Vec2f line_intersects(const vec_E< std::pair< Vec2f, Vec2f >> &lines)
Find intersection between multiple lines.
Definition: geometric_utils.h:94
vec_E< Vec3f > vec_Vec3f
Vector of type Vec3f.
Definition: data_type.h:92
Vecf< Dim > eigen_value(const Matf< Dim, Dim > &A)
Calculate eigen values.
Definition: geometric_utils.h:14
vec_E< Vec2f > vec_Vec2f
Vector of type Vec2f.
Definition: data_type.h:88