Apollo 9.0
自动驾驶开放平台
polygon2d.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <algorithm>
20#include <cmath>
21#include <limits>
22#include <utility>
23
24#include "absl/strings/str_cat.h"
25#include "absl/strings/str_join.h"
26
27#include "cyber/common/log.h"
30
31namespace apollo {
32namespace common {
33namespace math {
34
39
40Polygon2d::Polygon2d(std::vector<Vec2d> points, bool check_area)
41 : points_(std::move(points)) {
42 BuildFromPoints(check_area);
43}
44
45double Polygon2d::DistanceTo(const Vec2d &point) const {
46 CHECK_GE(points_.size(), 3U);
47 if (IsPointIn(point)) {
48 return 0.0;
49 }
50 double distance = std::numeric_limits<double>::infinity();
51 for (int i = 0; i < num_points_; ++i) {
52 distance = std::min(distance, line_segments_[i].DistanceTo(point));
53 }
54 return distance;
55}
56
57double Polygon2d::DistanceSquareTo(const Vec2d &point) const {
58 CHECK_GE(points_.size(), 3U);
59 if (IsPointIn(point)) {
60 return 0.0;
61 }
62 double distance_sqr = std::numeric_limits<double>::infinity();
63 for (int i = 0; i < num_points_; ++i) {
64 distance_sqr =
65 std::min(distance_sqr, line_segments_[i].DistanceSquareTo(point));
66 }
67 return distance_sqr;
68}
69
70double Polygon2d::DistanceTo(const LineSegment2d &line_segment) const {
71 if (line_segment.length() <= kMathEpsilon) {
72 return DistanceTo(line_segment.start());
73 }
74 CHECK_GE(points_.size(), 3U);
75 if (IsPointIn(line_segment.center())) {
76 return 0.0;
77 }
78 if (std::any_of(line_segments_.begin(), line_segments_.end(),
79 [&](const LineSegment2d &poly_seg) {
80 return poly_seg.HasIntersect(line_segment);
81 })) {
82 return 0.0;
83 }
84
85 double distance = std::min(DistanceTo(line_segment.start()),
86 DistanceTo(line_segment.end()));
87 for (int i = 0; i < num_points_; ++i) {
88 distance = std::min(distance, line_segment.DistanceTo(points_[i]));
89 }
90 return distance;
91}
92
93double Polygon2d::DistanceTo(const Box2d &box) const {
94 CHECK_GE(points_.size(), 3U);
95 return DistanceTo(Polygon2d(box));
96}
97
98double Polygon2d::DistanceTo(const Polygon2d &polygon) const {
99 CHECK_GE(points_.size(), 3U);
100 CHECK_GE(polygon.num_points(), 3);
101
102 if (IsPointIn(polygon.points()[0])) {
103 return 0.0;
104 }
105 if (polygon.IsPointIn(points_[0])) {
106 return 0.0;
107 }
108 double distance = std::numeric_limits<double>::infinity();
109 for (int i = 0; i < num_points_; ++i) {
110 distance = std::min(distance, polygon.DistanceTo(line_segments_[i]));
111 }
112 return distance;
113}
114
115double Polygon2d::DistanceToBoundary(const Vec2d &point) const {
116 double distance = std::numeric_limits<double>::infinity();
117 for (int i = 0; i < num_points_; ++i) {
118 distance = std::min(distance, line_segments_[i].DistanceTo(point));
119 }
120 return distance;
121}
122
123bool Polygon2d::IsPointOnBoundary(const Vec2d &point) const {
124 CHECK_GE(points_.size(), 3U);
125 return std::any_of(
126 line_segments_.begin(), line_segments_.end(),
127 [&](const LineSegment2d &poly_seg) { return poly_seg.IsPointIn(point); });
128}
129
130bool Polygon2d::IsPointIn(const Vec2d &point) const {
131 CHECK_GE(points_.size(), 3U);
132 if (IsPointOnBoundary(point)) {
133 return true;
134 }
135 int j = num_points_ - 1;
136 int c = 0;
137 for (int i = 0; i < num_points_; ++i) {
138 if ((points_[i].y() > point.y()) != (points_[j].y() > point.y())) {
139 const double side = CrossProd(point, points_[i], points_[j]);
140 if (points_[i].y() < points_[j].y() ? side > 0.0 : side < 0.0) {
141 ++c;
142 }
143 }
144 j = i;
145 }
146 return c & 1;
147}
148
149bool Polygon2d::HasOverlap(const Polygon2d &polygon) const {
150 CHECK_GE(points_.size(), 3U);
151 CHECK_GE(polygon.num_points(), 3);
152 if (polygon.max_x() < min_x() || polygon.min_x() > max_x() ||
153 polygon.max_y() < min_y() || polygon.min_y() > max_y()) {
154 return false;
155 }
156
157 if (IsPointIn(polygon.points()[0])) {
158 return true;
159 }
160
161 if (polygon.IsPointIn(points_[0])) {
162 return true;
163 }
164
165 for (int i = 0; i < polygon.num_points(); ++i) {
166 if (HasOverlap(polygon.line_segments()[i])) {
167 return true;
168 }
169 }
170 return false;
171}
172
173bool Polygon2d::Contains(const LineSegment2d &line_segment) const {
174 if (line_segment.length() <= kMathEpsilon) {
175 return IsPointIn(line_segment.start());
176 }
177 CHECK_GE(points_.size(), 3U);
178 if (!IsPointIn(line_segment.start())) {
179 return false;
180 }
181 if (!IsPointIn(line_segment.end())) {
182 return false;
183 }
184 if (!is_convex_) {
185 std::vector<LineSegment2d> overlaps = GetAllOverlaps(line_segment);
186 double total_length = 0;
187 for (const auto &overlap_seg : overlaps) {
188 total_length += overlap_seg.length();
189 }
190 return total_length >= line_segment.length() - kMathEpsilon;
191 }
192 return true;
193}
194
195bool Polygon2d::Contains(const Polygon2d &polygon) const {
196 CHECK_GE(points_.size(), 3U);
197 if (area_ < polygon.area() - kMathEpsilon) {
198 return false;
199 }
200 if (!IsPointIn(polygon.points()[0])) {
201 return false;
202 }
203 const auto &line_segments = polygon.line_segments();
204 return std::all_of(line_segments.begin(), line_segments.end(),
205 [&](const LineSegment2d &line_segment) {
206 return Contains(line_segment);
207 });
208}
209
210int Polygon2d::Next(int at) const { return at >= num_points_ - 1 ? 0 : at + 1; }
211
212int Polygon2d::Prev(int at) const { return at == 0 ? num_points_ - 1 : at - 1; }
213
214void Polygon2d::BuildFromPoints(bool check_area) {
215 num_points_ = static_cast<int>(points_.size());
216 CHECK_GE(num_points_, 3);
217
218 // Make sure the points are in ccw order.
219 area_ = 0.0;
220 for (int i = 1; i < num_points_; ++i) {
221 area_ += CrossProd(points_[0], points_[i - 1], points_[i]);
222 }
223 if (area_ < 0) {
224 area_ = -area_;
225 std::reverse(points_.begin(), points_.end());
226 }
227 area_ /= 2.0;
228 if (check_area) {
229 CHECK_GT(area_, kMathEpsilon);
230 }
231
232 // Construct line_segments.
234 for (int i = 0; i < num_points_; ++i) {
235 line_segments_.emplace_back(points_[i], points_[Next(i)]);
236 }
237
238 // Check convexity.
239 is_convex_ = true;
240 for (int i = 0; i < num_points_; ++i) {
241 if (CrossProd(points_[Prev(i)], points_[i], points_[Next(i)]) <=
242 -kMathEpsilon) {
243 is_convex_ = false;
244 break;
245 }
246 }
247
248 // Compute aabox.
249 min_x_ = points_[0].x();
250 max_x_ = points_[0].x();
251 min_y_ = points_[0].y();
252 max_y_ = points_[0].y();
253 for (const auto &point : points_) {
254 min_x_ = std::min(min_x_, point.x());
255 max_x_ = std::max(max_x_, point.x());
256 min_y_ = std::min(min_y_, point.y());
257 max_y_ = std::max(max_y_, point.y());
258 }
259}
260
261bool Polygon2d::ComputeConvexHull(const std::vector<Vec2d> &points,
262 Polygon2d *const polygon, bool check_area) {
263 CHECK_NOTNULL(polygon);
264 const int n = static_cast<int>(points.size());
265 if (n < 3) {
266 return false;
267 }
268 std::vector<int> sorted_indices(n);
269 for (int i = 0; i < n; ++i) {
270 sorted_indices[i] = i;
271 }
272 std::sort(sorted_indices.begin(), sorted_indices.end(),
273 [&](const int idx1, const int idx2) {
274 const Vec2d &pt1 = points[idx1];
275 const Vec2d &pt2 = points[idx2];
276 const double dx = pt1.x() - pt2.x();
277 if (std::abs(dx) > kMathEpsilon) {
278 return dx < 0.0;
279 }
280 return pt1.y() < pt2.y();
281 });
282 int count = 0;
283 std::vector<int> results;
284 results.reserve(n);
285 int last_count = 1;
286 for (int i = 0; i < n + n; ++i) {
287 if (i == n) {
288 last_count = count;
289 }
290 const int idx = sorted_indices[(i < n) ? i : (n + n - 1 - i)];
291 const Vec2d &pt = points[idx];
292 while (count > last_count &&
293 CrossProd(points[results[count - 2]], points[results[count - 1]],
294 pt) <= kMathEpsilon) {
295 results.pop_back();
296 --count;
297 }
298 results.push_back(idx);
299 ++count;
300 }
301 --count;
302 if (count < 3) {
303 return false;
304 }
305 std::vector<Vec2d> result_points;
306 result_points.reserve(count);
307 for (int i = 0; i < count; ++i) {
308 result_points.push_back(points[results[i]]);
309 }
310 *polygon = Polygon2d(result_points, check_area);
311 return true;
312}
313
314bool Polygon2d::ClipConvexHull(const LineSegment2d &line_segment,
315 std::vector<Vec2d> *const points) {
316 if (line_segment.length() <= kMathEpsilon) {
317 return true;
318 }
319 CHECK_NOTNULL(points);
320 const size_t n = points->size();
321 if (n < 3) {
322 return false;
323 }
324 std::vector<double> prod(n);
325 std::vector<int> side(n);
326 for (size_t i = 0; i < n; ++i) {
327 prod[i] = CrossProd(line_segment.start(), line_segment.end(), (*points)[i]);
328 if (std::abs(prod[i]) <= kMathEpsilon) {
329 side[i] = 0;
330 } else {
331 side[i] = ((prod[i] < 0) ? -1 : 1);
332 }
333 }
334
335 std::vector<Vec2d> new_points;
336 for (size_t i = 0; i < n; ++i) {
337 if (side[i] >= 0) {
338 new_points.push_back((*points)[i]);
339 }
340 const size_t j = ((i == n - 1) ? 0 : (i + 1));
341 if (side[i] * side[j] < 0) {
342 const double ratio = prod[j] / (prod[j] - prod[i]);
343 new_points.emplace_back(
344 (*points)[i].x() * ratio + (*points)[j].x() * (1.0 - ratio),
345 (*points)[i].y() * ratio + (*points)[j].y() * (1.0 - ratio));
346 }
347 }
348
349 points->swap(new_points);
350 return points->size() >= 3U;
351}
352
353bool Polygon2d::ComputeOverlap(const Polygon2d &other_polygon,
354 Polygon2d *const overlap_polygon) const {
355 CHECK_GE(points_.size(), 3U);
356 CHECK_NOTNULL(overlap_polygon);
357 ACHECK(is_convex_ && other_polygon.is_convex());
358 std::vector<Vec2d> points = other_polygon.points();
359 for (int i = 0; i < num_points_; ++i) {
360 if (!ClipConvexHull(line_segments_[i], &points)) {
361 return false;
362 }
363 }
364 return ComputeConvexHull(points, overlap_polygon, false);
365}
366
367double Polygon2d::ComputeIoU(const Polygon2d &other_polygon) const {
368 Polygon2d overlap_polygon;
369 if (!ComputeOverlap(other_polygon, &overlap_polygon)) {
370 return 0.0;
371 }
372 double intersection_area = overlap_polygon.area();
373 double union_area = area_ + other_polygon.area() - overlap_polygon.area();
374 return intersection_area / union_area;
375}
376
377bool Polygon2d::HasOverlap(const LineSegment2d &line_segment) const {
378 CHECK_GE(points_.size(), 3U);
379 if ((line_segment.start().x() < min_x_ && line_segment.end().x() < min_x_) ||
380 (line_segment.start().x() > max_x_ && line_segment.end().x() > max_x_) ||
381 (line_segment.start().y() < min_y_ && line_segment.end().y() < min_y_) ||
382 (line_segment.start().y() > max_y_ && line_segment.end().y() > max_y_)) {
383 return false;
384 }
385
386 if (std::any_of(line_segments_.begin(), line_segments_.end(),
387 [&](const LineSegment2d &poly_seg) {
388 return poly_seg.HasIntersect(line_segment);
389 })) {
390 return true;
391 }
392 return false;
393}
394
395bool Polygon2d::GetOverlap(const LineSegment2d &line_segment,
396 Vec2d *const first, Vec2d *const last) const {
397 CHECK_GE(points_.size(), 3U);
398 CHECK_NOTNULL(first);
399 CHECK_NOTNULL(last);
400
401 if (line_segment.length() <= kMathEpsilon) {
402 if (!IsPointIn(line_segment.start())) {
403 return false;
404 }
405 *first = line_segment.start();
406 *last = line_segment.start();
407 return true;
408 }
409
410 double min_proj = line_segment.length();
411 double max_proj = 0;
412 if (IsPointIn(line_segment.start())) {
413 *first = line_segment.start();
414 min_proj = 0.0;
415 }
416 if (IsPointIn(line_segment.end())) {
417 *last = line_segment.end();
418 max_proj = line_segment.length();
419 }
420 for (const auto &poly_seg : line_segments_) {
421 Vec2d pt;
422 if (poly_seg.GetIntersect(line_segment, &pt)) {
423 const double proj = line_segment.ProjectOntoUnit(pt);
424 if (proj < min_proj) {
425 min_proj = proj;
426 *first = pt;
427 }
428 if (proj > max_proj) {
429 max_proj = proj;
430 *last = pt;
431 }
432 }
433 }
434 return min_proj <= max_proj + kMathEpsilon;
435}
436
437void Polygon2d::GetAllVertices(std::vector<Vec2d> *const vertices) const {
438 if (vertices == nullptr) {
439 return;
440 }
441 *vertices = points_;
442}
443
444std::vector<Vec2d> Polygon2d::GetAllVertices() const { return points_; }
445
446std::vector<LineSegment2d> Polygon2d::GetAllOverlaps(
447 const LineSegment2d &line_segment) const {
448 CHECK_GE(points_.size(), 3U);
449
450 if (line_segment.length() <= kMathEpsilon) {
451 std::vector<LineSegment2d> overlaps;
452 if (IsPointIn(line_segment.start())) {
453 overlaps.push_back(line_segment);
454 }
455 return overlaps;
456 }
457 std::vector<double> projections;
458 if (IsPointIn(line_segment.start())) {
459 projections.push_back(0.0);
460 }
461 if (IsPointIn(line_segment.end())) {
462 projections.push_back(line_segment.length());
463 }
464 for (const auto &poly_seg : line_segments_) {
465 Vec2d pt;
466 if (poly_seg.GetIntersect(line_segment, &pt)) {
467 projections.push_back(line_segment.ProjectOntoUnit(pt));
468 }
469 }
470 std::sort(projections.begin(), projections.end());
471 std::vector<std::pair<double, double>> overlaps;
472 for (size_t i = 0; i + 1 < projections.size(); ++i) {
473 const double start_proj = projections[i];
474 const double end_proj = projections[i + 1];
475 if (end_proj - start_proj <= kMathEpsilon) {
476 continue;
477 }
478 const Vec2d reference_point =
479 line_segment.start() +
480 (start_proj + end_proj) / 2.0 * line_segment.unit_direction();
481 if (!IsPointIn(reference_point)) {
482 continue;
483 }
484 if (overlaps.empty() ||
485 start_proj > overlaps.back().second + kMathEpsilon) {
486 overlaps.emplace_back(start_proj, end_proj);
487 } else {
488 overlaps.back().second = end_proj;
489 }
490 }
491 std::vector<LineSegment2d> overlap_line_segments;
492 for (const auto &overlap : overlaps) {
493 overlap_line_segments.emplace_back(
494 line_segment.start() + overlap.first * line_segment.unit_direction(),
495 line_segment.start() + overlap.second * line_segment.unit_direction());
496 }
497 return overlap_line_segments;
498}
499
500void Polygon2d::ExtremePoints(const double heading, Vec2d *const first,
501 Vec2d *const last) const {
502 CHECK_GE(points_.size(), 3U);
503 CHECK_NOTNULL(first);
504 CHECK_NOTNULL(last);
505
506 const Vec2d direction_vec = Vec2d::CreateUnitVec2d(heading);
507 double min_proj = std::numeric_limits<double>::infinity();
508 double max_proj = -std::numeric_limits<double>::infinity();
509 for (const auto &pt : points_) {
510 const double proj = pt.InnerProd(direction_vec);
511 if (proj < min_proj) {
512 min_proj = proj;
513 *first = pt;
514 }
515 if (proj > max_proj) {
516 max_proj = proj;
517 *last = pt;
518 }
519 }
520}
521
522AABox2d Polygon2d::AABoundingBox() const {
523 return AABox2d({min_x_, min_y_}, {max_x_, max_y_});
524}
525
526Box2d Polygon2d::BoundingBoxWithHeading(const double heading) const {
527 CHECK_GE(points_.size(), 3U);
528 const Vec2d direction_vec = Vec2d::CreateUnitVec2d(heading);
529 Vec2d px1;
530 Vec2d px2;
531 Vec2d py1;
532 Vec2d py2;
533 ExtremePoints(heading, &px1, &px2);
534 ExtremePoints(heading - M_PI_2, &py1, &py2);
535 const double x1 = px1.InnerProd(direction_vec);
536 const double x2 = px2.InnerProd(direction_vec);
537 const double y1 = py1.CrossProd(direction_vec);
538 const double y2 = py2.CrossProd(direction_vec);
539 return Box2d(
540 (x1 + x2) / 2.0 * direction_vec +
541 (y1 + y2) / 2.0 * Vec2d(direction_vec.y(), -direction_vec.x()),
542 heading, x2 - x1, y2 - y1);
543}
544
545Box2d Polygon2d::MinAreaBoundingBox() const {
546 CHECK_GE(points_.size(), 3U);
547 if (!is_convex_) {
548 Polygon2d convex_polygon;
549 ComputeConvexHull(points_, &convex_polygon);
550 ACHECK(convex_polygon.is_convex());
551 return convex_polygon.MinAreaBoundingBox();
552 }
553 double min_area = std::numeric_limits<double>::infinity();
554 double min_area_at_heading = 0.0;
555 int left_most = 0;
556 int right_most = 0;
557 int top_most = 0;
558 for (int i = 0; i < num_points_; ++i) {
559 const auto &line_segment = line_segments_[i];
560 double proj = 0.0;
561 double min_proj = line_segment.ProjectOntoUnit(points_[left_most]);
562 while ((proj = line_segment.ProjectOntoUnit(points_[Prev(left_most)])) <
563 min_proj) {
564 min_proj = proj;
565 left_most = Prev(left_most);
566 }
567 while ((proj = line_segment.ProjectOntoUnit(points_[Next(left_most)])) <
568 min_proj) {
569 min_proj = proj;
570 left_most = Next(left_most);
571 }
572 double max_proj = line_segment.ProjectOntoUnit(points_[right_most]);
573 while ((proj = line_segment.ProjectOntoUnit(points_[Prev(right_most)])) >
574 max_proj) {
575 max_proj = proj;
576 right_most = Prev(right_most);
577 }
578 while ((proj = line_segment.ProjectOntoUnit(points_[Next(right_most)])) >
579 max_proj) {
580 max_proj = proj;
581 right_most = Next(right_most);
582 }
583 double prod = 0.0;
584 double max_prod = line_segment.ProductOntoUnit(points_[top_most]);
585 while ((prod = line_segment.ProductOntoUnit(points_[Prev(top_most)])) >
586 max_prod) {
587 max_prod = prod;
588 top_most = Prev(top_most);
589 }
590 while ((prod = line_segment.ProductOntoUnit(points_[Next(top_most)])) >
591 max_prod) {
592 max_prod = prod;
593 top_most = Next(top_most);
594 }
595 const double area = max_prod * (max_proj - min_proj);
596 if (area < min_area) {
597 min_area = area;
598 min_area_at_heading = line_segment.heading();
599 }
600 }
601 return BoundingBoxWithHeading(min_area_at_heading);
602}
603
604Polygon2d Polygon2d::ExpandByDistance(const double distance) const {
605 if (!is_convex_) {
606 Polygon2d convex_polygon;
607 ComputeConvexHull(points_, &convex_polygon);
608 ACHECK(convex_polygon.is_convex());
609 return convex_polygon.ExpandByDistance(distance);
610 }
611 const double kMinAngle = 0.1;
612 std::vector<Vec2d> points;
613 for (int i = 0; i < num_points_; ++i) {
614 const double start_angle = line_segments_[Prev(i)].heading() - M_PI_2;
615 const double end_angle = line_segments_[i].heading() - M_PI_2;
616 const double diff = WrapAngle(end_angle - start_angle);
617 if (diff <= kMathEpsilon) {
618 points.push_back(points_[i] +
619 Vec2d::CreateUnitVec2d(start_angle) * distance);
620 } else {
621 const int count = static_cast<int>(diff / kMinAngle) + 1;
622 for (int k = 0; k <= count; ++k) {
623 const double angle = start_angle + diff * static_cast<double>(k) /
624 static_cast<double>(count);
625 points.push_back(points_[i] + Vec2d::CreateUnitVec2d(angle) * distance);
626 }
627 }
628 }
629 Polygon2d new_polygon;
630 ACHECK(ComputeConvexHull(points, &new_polygon));
631 return new_polygon;
632}
633
634Polygon2d Polygon2d::PolygonExpandByDistance(const double distance) const {
635 if (!is_convex_) {
636 Polygon2d convex_polygon;
637 ComputeConvexHull(points_, &convex_polygon);
638 ACHECK(convex_polygon.is_convex());
639 return convex_polygon.PolygonExpandByDistance(distance);
640 }
641 std::vector<Vec2d> points;
642 for (int i = 0; i < num_points_; ++i) {
643 double v1x = points_[Prev(i)].x() - points_[i].x();
644 double v1y = points_[Prev(i)].y() - points_[i].y();
645 double n1 = std::sqrt(v1x * v1x + v1y * v1y);
646 v1x /= n1;
647 v1y /= n1;
648
649 double v2x = points_[Next(i)].x() - points_[i].x();
650 double v2y = points_[Next(i)].y() - points_[i].y();
651 double n2 = std::sqrt(v2x * v2x + v2y * v2y);
652 v2x /= n2;
653 v2x /= n2;
654
655 double l = distance / sqrt((1 - (v1x * v2x + v1y * v2y)) / 2);
656
657 double vx = v1x + v2x;
658 double vy = v1y + v2y;
659 double n = l / sqrt(vx * vx + vy * vy);
660
661 vx *= n;
662 vy *= n;
663
664 Vec2d point(vx + points_[i].x(), vy + points_[i].y());
665 points.push_back(point);
666 }
667 Polygon2d new_polygon;
668 ACHECK(ComputeConvexHull(points, &new_polygon));
669 return new_polygon;
670}
671
672void Polygon2d::CalculateVertices(const Vec2d &shift_vec) {
673 for (size_t i = 0; i < num_points_; ++i) {
674 points_[i] += shift_vec;
675 }
676 for (auto &point : points_) {
677 max_x_ = std::fmax(point.x(), max_x_);
678 min_x_ = std::fmin(point.x(), min_x_);
679 max_y_ = std::fmax(point.y(), max_y_);
680 min_y_ = std::fmin(point.y(), min_y_);
681 }
682}
683
684LineSegment2d Polygon2d::MinLineSegment() const {
685 double min_length_of_line_segment = 10e3;
686 LineSegment2d line_segment;
687 for (auto &line_segment_ : line_segments_) {
688 if (line_segment_.length() < min_length_of_line_segment) {
689 line_segment = line_segment_;
690 }
691 }
692 return line_segment;
693}
694
695std::string Polygon2d::DebugString() const {
696 return absl::StrCat("polygon2d ( num_points = ", num_points_, " points = (",
697 absl::StrJoin(points_, " ", util::DebugStringFormatter()),
698 " ) ", is_convex_ ? "convex" : "non-convex",
699 " area = ", area_, " )");
700}
701
702} // namespace math
703} // namespace common
704} // namespace apollo
Implements a class of (undirected) axes-aligned bounding boxes in 2-D.
Definition aabox2d.h:42
Rectangular (undirected) bounding box in 2-D.
Definition box2d.h:52
void GetAllCorners(std::vector< Vec2d > *const corners) const
Getter of the corners of the box
Definition box2d.cc:140
const Vec2d & end() const
Get the end point.
const Vec2d & unit_direction() const
Get the unit direction from the start point to the end point.
double ProjectOntoUnit(const Vec2d &point) const
Compute the projection of a vector onto the line segment.
double length() const
Get the length of the line segment.
double DistanceTo(const Vec2d &point) const
Compute the shortest distance from a point on the line segment to a point in 2-D.
const Vec2d & start() const
Get the start point.
Vec2d center() const
Get the center of the line segment.
The class of polygon in 2-D.
Definition polygon2d.h:42
std::vector< LineSegment2d > GetAllOverlaps(const LineSegment2d &line_segment) const
Get all overlapped line segments of a line segment and this polygon.
Definition polygon2d.cc:446
bool HasOverlap(const LineSegment2d &line_segment) const
Check if a line segment has overlap with this polygon.
Definition polygon2d.cc:377
std::vector< Vec2d > points_
Definition polygon2d.h:333
bool IsPointIn(const Vec2d &point) const
Check if a point is within the polygon.
Definition polygon2d.cc:130
static bool ComputeConvexHull(const std::vector< Vec2d > &points, Polygon2d *const polygon, bool check_area=true)
Compute the convex hull of a group of points.
Definition polygon2d.cc:261
bool Contains(const LineSegment2d &line_segment) const
Check if the polygon contains a line segment.
Definition polygon2d.cc:173
Polygon2d()=default
Empty constructor.
Polygon2d ExpandByDistance(const double distance) const
Expand this polygon by a distance.
Definition polygon2d.cc:604
Box2d MinAreaBoundingBox() const
Get the bounding box with the minimal area.
Definition polygon2d.cc:545
double DistanceTo(const Vec2d &point) const
Compute the distance from a point to the polygon.
Definition polygon2d.cc:45
const std::vector< LineSegment2d > & line_segments() const
Get the edges of the polygon.
Definition polygon2d.h:71
const std::vector< Vec2d > & points() const
Get the vertices of the polygon.
Definition polygon2d.h:65
double DistanceSquareTo(const Vec2d &point) const
Compute the square of distance from a point to the polygon.
Definition polygon2d.cc:57
void BuildFromPoints(bool check_area=true)
Definition polygon2d.cc:214
std::vector< LineSegment2d > line_segments_
Definition polygon2d.h:335
bool IsPointOnBoundary(const Vec2d &point) const
Check if a point is on the boundary of the polygon.
Definition polygon2d.cc:123
int num_points() const
Get the number of vertices of the polygon.
Definition polygon2d.h:79
Polygon2d PolygonExpandByDistance(const double distance) const
Definition polygon2d.cc:634
bool is_convex() const
Check if the polygon is convex.
Definition polygon2d.h:85
double area() const
Get the area of the polygon.
Definition polygon2d.h:91
double DistanceToBoundary(const Vec2d &point) const
Compute the distance from a point to the boundary of the polygon.
Definition polygon2d.cc:115
Implements a class of 2-dimensional vectors.
Definition vec2d.h:42
double InnerProd(const Vec2d &other) const
Returns the inner product between these two Vec2d.
Definition vec2d.cc:61
double y() const
Getter for y component
Definition vec2d.h:57
double x() const
Getter for x component
Definition vec2d.h:54
double CrossProd(const Vec2d &other) const
Returns the "cross" product between these two Vec2d (non-standard).
Definition vec2d.cc:57
#define ACHECK(cond)
Definition log.h:80
Math-related util functions.
constexpr double kMathEpsilon
Definition vec2d.h:35
double CrossProd(const Vec2d &start_point, const Vec2d &end_point_1, const Vec2d &end_point_2)
Cross product between two 2-D vectors from the common start point, and end at two other points.
Definition math_utils.cc:28
double WrapAngle(const double angle)
Wrap angle to [0, 2 * PI).
Definition math_utils.cc:48
class register implement
Definition future.h:29
Define the Polygon2d class.
Some string util functions.