31template <
class CLOUD_IN_TYPE,
class CLOUD_OUT_TYPE>
34 template <
class EigenType>
39 points_.reserve(1000.0);
40 polygon_indices_.reserve(1000.0);
45 CLOUD_OUT_TYPE* out_polygon) {
47 if (!GetConvexHullMonotoneChain(out_polygon)) {
48 return MockConvexHull(out_polygon);
54 const float& distance_above_ground_thres,
55 CLOUD_OUT_TYPE* out_polygon) {
56 CLOUD_IN_TYPE in_cloud_without_ground;
57 in_cloud_without_ground.reserve(in_cloud.size());
58 for (std::size_t
id = 0;
id < in_cloud.size(); ++id) {
61 if (in_cloud.points_height(
id) >= distance_above_ground_thres) {
62 in_cloud_without_ground.push_back(in_cloud[
id]);
65 if (in_cloud_without_ground.empty()) {
68 SetPoints(in_cloud_without_ground);
69 if (!GetConvexHullMonotoneChain(out_polygon)) {
70 return MockConvexHull(out_polygon);
78 const CLOUD_IN_TYPE& in_cloud,
const float& distance_above_ground_thres,
79 const float& distance_beneath_head_thres, CLOUD_OUT_TYPE* out_polygon) {
80 CLOUD_IN_TYPE in_cloud_without_ground_and_head;
81 in_cloud_without_ground_and_head.reserve(in_cloud.size());
82 for (std::size_t
id = 0;
id < in_cloud.size(); ++id) {
85 if (in_cloud.points_height(
id) == std::numeric_limits<float>::max() ||
86 (in_cloud.points_height(
id) >= distance_above_ground_thres &&
87 in_cloud.points_height(
id) <= distance_beneath_head_thres)) {
88 in_cloud_without_ground_and_head.push_back(in_cloud[
id]);
91 if (in_cloud_without_ground_and_head.empty()) {
94 SetPoints(in_cloud_without_ground_and_head);
95 if (!GetConvexHullMonotoneChain(out_polygon)) {
96 return MockConvexHull(out_polygon);
104 void SetPoints(
const CLOUD_IN_TYPE& in_cloud);
106 bool MockConvexHull(CLOUD_OUT_TYPE* out_polygon);
108 bool GetConvexHullMonotoneChain(CLOUD_OUT_TYPE* out_polygon);
110 bool IsCounterClockWise(
const Eigen::Vector2d& p1,
const Eigen::Vector2d& p2,
111 const Eigen::Vector2d& p3,
const double& eps) {
112 Eigen::Vector2d p12 = p2 - p1;
113 Eigen::Vector2d p13 = p3 - p1;
114 return (p12(0) * p13(1) - p12(1) * p13(0) > eps);
118 EigenVector<Eigen::Vector2d> points_;
119 std::vector<std::size_t> polygon_indices_;
120 const CLOUD_IN_TYPE* in_cloud_;
123template <
class CLOUD_IN_TYPE,
class CLOUD_OUT_TYPE>
124void ConvexHull2D<CLOUD_IN_TYPE, CLOUD_OUT_TYPE>::SetPoints(
125 const CLOUD_IN_TYPE& in_cloud) {
126 points_.resize(in_cloud.size());
127 for (std::size_t i = 0; i < points_.size(); ++i) {
128 points_[i] << in_cloud[i].x, in_cloud[i].y;
130 in_cloud_ = &in_cloud;
133template <
class CLOUD_IN_TYPE,
class CLOUD_OUT_TYPE>
134bool ConvexHull2D<CLOUD_IN_TYPE, CLOUD_OUT_TYPE>::MockConvexHull(
135 CLOUD_OUT_TYPE* out_polygon) {
136 if (in_cloud_->size() == 0) {
139 out_polygon->resize(4);
140 Eigen::Matrix<double, 3, 1> maxv;
141 Eigen::Matrix<double, 3, 1> minv;
142 maxv << in_cloud_->at(0).x, in_cloud_->at(0).y, in_cloud_->at(0).z;
144 for (std::size_t i = 1; i < in_cloud_->size(); ++i) {
145 maxv(0) = std::max<double>(maxv(0), in_cloud_->at(i).x);
146 maxv(1) = std::max<double>(maxv(1), in_cloud_->at(i).y);
147 maxv(2) = std::max<double>(maxv(2), in_cloud_->at(i).z);
149 minv(0) = std::min<double>(minv(0), in_cloud_->at(i).x);
150 minv(1) = std::min<double>(minv(1), in_cloud_->at(i).y);
151 minv(2) = std::min<double>(minv(2), in_cloud_->at(i).z);
154 static const double eps = 1e-3;
155 for (std::size_t i = 0; i < 3; ++i) {
156 if (maxv(i) - minv(i) < eps) {
163 out_polygon->at(0).x = minv(0);
164 out_polygon->at(0).y = minv(1);
165 out_polygon->at(0).z = minv(2);
167 out_polygon->at(1).x = maxv(0);
168 out_polygon->at(1).y = minv(1);
169 out_polygon->at(1).z = minv(2);
171 out_polygon->at(2).x = maxv(0);
172 out_polygon->at(2).y = maxv(1);
173 out_polygon->at(2).z = minv(2);
175 out_polygon->at(3).x = minv(0);
176 out_polygon->at(3).y = maxv(1);
177 out_polygon->at(3).z = minv(2);
181template <
class CLOUD_IN_TYPE,
class CLOUD_OUT_TYPE>
182bool ConvexHull2D<CLOUD_IN_TYPE, CLOUD_OUT_TYPE>::GetConvexHullMonotoneChain(
183 CLOUD_OUT_TYPE* out_polygon) {
184 if (points_.size() < 3) {
188 std::vector<std::size_t> sorted_indices(points_.size());
189 std::iota(sorted_indices.begin(), sorted_indices.end(), 0);
191 static const double eps = 1e-9;
192 std::sort(sorted_indices.begin(), sorted_indices.end(),
193 [&](
const std::size_t& lhs,
const std::size_t& rhs) {
194 double dx = points_[lhs](0) - points_[rhs](0);
195 if (std::abs(dx) > eps) {
198 return points_[lhs](1) < points_[rhs](1);
202 polygon_indices_.clear();
203 polygon_indices_.reserve(points_.size());
205 std::size_t size2 = points_.size() * 2;
206 for (std::size_t i = 0; i < size2; ++i) {
207 if (i == points_.size()) {
210 const std::size_t& idx =
211 sorted_indices[(i < points_.size()) ? i : (size2 - 1 - i)];
212 const auto& point = points_[idx];
213 while (count > last_count &&
214 !IsCounterClockWise(points_[polygon_indices_[count - 2]],
215 points_[polygon_indices_[count - 1]], point,
217 polygon_indices_.pop_back();
220 polygon_indices_.push_back(idx);
224 polygon_indices_.pop_back();
228 out_polygon->clear();
229 out_polygon->resize(polygon_indices_.size());
231 double min_z = in_cloud_->at(0).z;
232 for (std::size_t
id = 0;
id < in_cloud_->size(); ++id) {
233 min_z = std::min<double>(in_cloud_->at(
id).z, min_z);
235 for (std::size_t i = 0; i < polygon_indices_.size(); ++i) {
236 out_polygon->at(i).x = points_[polygon_indices_[i]](0);
237 out_polygon->at(i).y = points_[polygon_indices_[i]](1);
238 out_polygon->at(i).z = min_z;
bool GetConvexHullWithoutGroundAndHead(const CLOUD_IN_TYPE &in_cloud, const float &distance_above_ground_thres, const float &distance_beneath_head_thres, CLOUD_OUT_TYPE *out_polygon)
bool GetConvexHull(const CLOUD_IN_TYPE &in_cloud, CLOUD_OUT_TYPE *out_polygon)
bool GetConvexHullWithoutGround(const CLOUD_IN_TYPE &in_cloud, const float &distance_above_ground_thres, CLOUD_OUT_TYPE *out_polygon)
apollo::common::EigenVector< EigenType > EigenVector
std::vector< EigenType, Eigen::aligned_allocator< EigenType > > EigenVector