25#include "Eigen/StdVector"
33template <
typename T =
double>
36 typedef Eigen::Matrix<T, 2, 1>
Point;
37 typedef std::vector<Point, Eigen::aligned_allocator<Point>>
Polygon;
45 if (delta_x < 0 || !std::isfinite(
k)) {
57 "max_x: %13.10lf max_y: %13.10lf"
58 "min_x: %13.10lf min_y: %13.10lf"
59 "x: %13.10lf y: %13.10lf k %13.10lf") %
124 std::vector<IntervalOut>* scan_intervals);
136 std::vector<std::vector<IntervalOut>>* scans_intervals);
143 void ParsePolygon(
const DirectionMajor dir_major,
const bool disturb =
false);
145 void UpdateAet(std::vector<IntervalOut>* scan_intervals);
147 bool ConvertSegment(
const size_t seg_id, std::pair<int, Edge>* out_edge);
151 std::vector<std::vector<bool>> is_singular_;
152 std::vector<std::vector<Segment>> segments_;
154 std::vector<std::vector<double>> ks_;
156 std::vector<std::pair<double, double>> top_segments_;
159 std::vector<std::vector<Edge>> et_;
161 std::pair<size_t, std::vector<Edge>> aet_;
162 double bottom_x_ = 0.0;
164 size_t scans_size_ = 0;
171 std::numeric_limits<float>::epsilon();
180 is_singular_.resize(2);
188 is_singular_.clear();
195 std::vector<IntervalOut>* scan_intervals) {
198 auto& is_singular = is_singular_[dir_major];
199 auto& segments = segments_[dir_major];
200 auto& ks = ks_[dir_major];
201 CHECK_EQ(segments.size(), polygon_.size());
202 CHECK_EQ(segments.size(), ks.size());
203 scan_intervals->clear();
204 scan_intervals->reserve(polygon_.size());
205 std::vector<double> nodes;
206 nodes.reserve(polygon_.size());
208 for (
size_t i = 0; i < segments.size(); ++i) {
209 const Segment& segment = segments[i];
210 const Point& low_vertex = segment.first;
211 const Point& high_vertex = segment.second;
212 double high_x = high_vertex[dir_major];
213 double high_y = high_vertex[op_dir_major];
214 double low_x = low_vertex[dir_major];
215 double low_y = low_vertex[op_dir_major];
217 if (std::isfinite(k)) {
218 if ((x >= low_x && x < high_x) || (x <= low_x && x > high_x)) {
219 if (std::fabs(x - low_x) < 1.0e-6) {
220 nodes.push_back(low_y);
221 if (is_singular[i]) {
222 nodes.push_back(low_y);
225 nodes.push_back(low_y + (x - low_x) * k);
229 if (std::abs(x - low_x) < s_epsilon_ ||
230 std::abs(x - high_x) < s_epsilon_) {
231 if (low_y < high_y) {
232 scan_intervals->push_back(
IntervalOut(low_y, high_y));
234 scan_intervals->push_back(
IntervalOut(high_y, low_y));
239 CHECK_EQ(nodes.size() % 2,
static_cast<size_t>(0));
240 std::sort(nodes.begin(), nodes.end());
241 for (
size_t i = 0; i < nodes.size(); i += 2) {
242 scan_intervals->push_back(
IntervalOut(nodes[i], nodes[i + 1]));
249 const T& step, std::vector<std::vector<IntervalOut>>* scans_intervals) {
250 dir_major_ = dir_major;
251 op_dir_major_ = OppositeDirection(dir_major_);
254 CHECK_GT(scans_interval.second, scans_interval.first + step);
256 bottom_x_ = scans_interval.first;
257 double top_x = scans_interval.second;
258 scans_size_ =
static_cast<size_t>((top_x - bottom_x_) / step_);
260 top_segments_.clear();
261 top_segments_.reserve(2);
263 ParsePolygon(dir_major,
true);
266 scans_intervals->clear();
267 scans_intervals->resize(scans_size_);
271 (*scans_intervals)[0].reserve(polygon_.size());
273 for (
const auto& edge : et_[0]) {
274 if (std::isfinite(edge.k)) {
275 aet_.second.push_back(edge);
277 (*scans_intervals)[0].push_back(
IntervalOut(edge.y, edge.max_y));
281 std::sort(aet_.second.begin(), aet_.second.end());
282 CHECK_EQ(aet_.second.size() & 1,
static_cast<size_t>(0));
285 for (
size_t i = 0; i < aet_.second.size(); i += 2) {
286 double min_y = aet_.second[i].y;
287 double max_y = aet_.second[i + 1].y;
288 (*scans_intervals)[0].push_back(
IntervalOut(min_y, max_y));
290 for (
size_t i = 1; i < scans_size_; ++i) {
291 UpdateAet(&((*scans_intervals)[i]));
294 if (top_segments_.size()) {
295 scans_intervals->resize(scans_size_ + 1);
296 for (
auto& seg : top_segments_) {
297 double y1 = seg.first;
298 double y2 = seg.second;
299 double min_y = std::min(y1, y2);
300 double max_y = std::max(y1, y2);
301 (*scans_intervals)[scans_size_].push_back(
IntervalOut(min_y, max_y));
308 for (
auto& pt : polygon_disturbed_) {
309 T& x = pt[dir_major];
310 double d_x = (x - bottom_x_) / step_;
311 int int_d_x =
static_cast<int>(std::round(d_x));
312 double delta_x = d_x - int_d_x;
313 if (std::abs(delta_x) < s_epsilon_) {
315 x =
static_cast<T
>((int_d_x + s_epsilon_) * step_ + bottom_x_);
317 x =
static_cast<T
>((int_d_x - s_epsilon_) * step_ + bottom_x_);
324void PolygonScanCvter<T>::ParsePolygon(
const DirectionMajor dir_major,
325 const bool disturb) {
326 polygon_disturbed_ = polygon_;
328 DisturbPolygon(dir_major);
331 size_t vertices_size = polygon_disturbed_.size();
332 is_singular_[dir_major].clear();
333 is_singular_[dir_major].reserve(vertices_size);
334 segments_[dir_major].clear();
335 segments_[dir_major].reserve(vertices_size);
336 ks_[dir_major].clear();
337 ks_[dir_major].reserve(vertices_size);
339 auto& is_singular = is_singular_[dir_major];
340 auto& segments = segments_[dir_major];
341 auto& ks = ks_[dir_major];
343 for (
size_t i = 0; i < vertices_size; ++i) {
344 const Point& pre_vertex =
345 polygon_disturbed_[(i + vertices_size - 1) % vertices_size];
346 const Point& vertex = polygon_disturbed_[i];
347 const Point& nex_vertex = polygon_disturbed_[(i + 1) % vertices_size];
348 T pre_x = pre_vertex[dir_major];
349 T x = vertex[dir_major];
350 T y = vertex[op_dir_major];
351 T nex_x = nex_vertex[dir_major];
352 T nex_y = nex_vertex[op_dir_major];
355 Segment line_seg(vertex, nex_vertex);
356 double x_diff = nex_x - x;
357 double y_diff = nex_y - y;
360 segments.push_back(line_seg);
361 std::abs(x_diff) < s_epsilon_ ? ks.push_back(s_inf_)
362 : ks.push_back(y_diff / x_diff);
363 double pre_x_diff = pre_x - x;
368 if (std::abs(x_diff) < s_epsilon_ || std::abs(pre_x_diff) < s_epsilon_) {
369 is_singular.push_back(
true);
371 pre_x_diff* x_diff > 0 ? is_singular.push_back(
true)
372 : is_singular.push_back(
false);
378void PolygonScanCvter<T>::BuildEt() {
379 const auto& segments = segments_[dir_major_];
382 et_.resize(scans_size_);
383 for (
auto& edge_list : et_) {
384 edge_list.reserve(polygon_.size());
388 std::vector<std::pair<int, Edge>> edges;
389 edges.reserve(segments.size());
390 for (
size_t i = 0; i < segments.size(); ++i) {
391 std::pair<int, Edge> out_edge;
392 if (ConvertSegment(i, &(out_edge))) {
393 edges.push_back(out_edge);
400 aet_.second.reserve(segments.size());
401 for (
size_t i = 0; i < edges.size(); ++i) {
402 int x_id = edges[i].first;
403 const Edge& edge = edges[i].second;
404 if (x_id >=
static_cast<int>(scans_size_)) {
409 et_[x_id].push_back(edge);
412 Edge active_edge = edge;
413 if (active_edge.MoveUp(0.0 - active_edge.x)) {
414 aet_.second.push_back(active_edge);
421void PolygonScanCvter<T>::UpdateAet(std::vector<IntervalOut>* scan_intervals) {
422 size_t x_id = aet_.first + 1;
423 CHECK_LT(x_id, et_.size());
425 scan_intervals->clear();
426 scan_intervals->reserve(polygon_.size());
429 size_t valid_edges_num = aet_.second.size();
430 size_t invalid_edges_num = 0;
431 for (
auto& edge : aet_.second) {
432 if (!edge.MoveUp(step_)) {
440 size_t new_edges_num = 0;
441 for (
const auto& edge : et_[x_id]) {
442 if (std::isfinite(edge.k)) {
445 aet_.second.push_back(edge);
447 scan_intervals->push_back(IntervalOut(edge.y, edge.max_y));
450 CHECK_EQ(valid_edges_num & 1,
static_cast<size_t>(0))
452 "valid edges num: %d x: %lf bottom_x: %lf \n vertices num: %d "
454 valid_edges_num % (x_id * step_ + bottom_x_) % bottom_x_ %
456 << aet_.second[0] <<
"\n"
457 << aet_.second[1] <<
"\n"
458 << aet_.second[2] <<
"\n"
462 if (invalid_edges_num != 0 || new_edges_num != 0) {
463 std::sort(aet_.second.begin(), aet_.second.end());
465 aet_.second.resize(valid_edges_num);
467 for (
size_t i = 0; i < aet_.second.size(); i += 2) {
469 double min_y = aet_.second[i].y;
470 double max_y = aet_.second[i + 1].y;
471 scan_intervals->push_back(IntervalOut(min_y, max_y));
476bool PolygonScanCvter<T>::ConvertSegment(
const size_t seg_id,
477 std::pair<int, Edge>* out_edge) {
478 const auto& segments = segments_[dir_major_];
479 const auto& ks = ks_[dir_major_];
481 CHECK_LT(seg_id, segments.size());
482 Segment segment = segments[seg_id];
483 double k = ks[seg_id];
484 const Point& low_vertex = segment.first;
485 const Point& high_vertex = segment.second;
486 if (low_vertex[dir_major_] > high_vertex[dir_major_]) {
487 std::swap(segment.first, segment.second);
490 Edge& edge = out_edge->second;
491 int& x_id = out_edge->first;
492 const Point& min_vertex = segment.first;
493 double min_x = min_vertex[dir_major_] - bottom_x_;
494 double min_y = min_vertex[op_dir_major_];
495 x_id =
static_cast<int>(std::ceil(min_x / step_));
496 double min_x_ceil = x_id * step_;
500 edge.max_x = segment.second[dir_major_] - bottom_x_;
501 edge.max_y = segment.second[op_dir_major_];
504 if (std::isfinite(edge.k)) {
505 edge.y = min_y + (edge.x - min_x) * edge.k;
509 if (edge.y > edge.max_y) {
510 std::swap(edge.y, edge.max_y);
516 if (
static_cast<size_t>(x_id) >= scans_size_) {
517 std::pair<double, double> seg(low_vertex[op_dir_major_],
518 high_vertex[op_dir_major_]);
519 top_segments_.push_back(seg);
522 if (std::isfinite(edge.k) && edge.max_x < edge.x) {
void Init(const Polygon &polygon)
Init of Polygon Scan Cvter object
void ScanCvt(const T &scan_loc, DirectionMajor dir_major, std::vector< IntervalOut > *scan_intervals)
Get scan intervals
std::pair< double, double > IntervalOut
PolygonScanCvter()=default
Construct a new Polygon Scan Cvter object
const Polygon & polygon() const
Return the polygon_
void ScansCvt(const IntervalIn &scans_interval, const DirectionMajor dir_major, const T &step, std::vector< std::vector< IntervalOut > > *scans_intervals)
Get scan intervals
std::pair< T, T > IntervalIn
static const double s_epsilon_
void Reset()
Reset the Polygon Scan Cvter object
std::pair< Point, Point > Segment
std::vector< Point, Eigen::aligned_allocator< Point > > Polygon
virtual ~PolygonScanCvter()=default
Destroy the Polygon Scan Cvter object
static const double s_inf_
Eigen::Matrix< T, 2, 1 > Point
static DirectionMajor OppositeDirection(const DirectionMajor dir_major)
typename PolygonScanCvter< T >::Polygon Polygon
Bitmap2D::DirectionMajor DirectionMajor
apollo::common::Point3D Point
friend std::ostream & operator<<(std::ostream &out, const Edge &edge)
bool operator<(const Edge &other) const
bool MoveUp(double delta_x)