Skip to content

Commit 577a87e

Browse files
committed
make within() support concave polygons
Signed-off-by: mitukou1109 <mitukou1109@gmail.com>
1 parent d9bab4f commit 577a87e

File tree

3 files changed

+233
-37
lines changed

3 files changed

+233
-37
lines changed

common/autoware_universe_utils/include/autoware/universe_utils/geometry/alt_geometry.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ bool within(const alt::Point2d & point, const alt::PointList2d & ring);
209209

210210
bool within(const alt::Point2d & point, const alt::Polygon2d & poly);
211211

212-
bool within(const alt::Polygon2d & poly_contained, const alt::ConvexPolygon2d & poly_containing);
212+
bool within(const alt::Polygon2d & poly_contained, const alt::Polygon2d & poly_containing);
213213
} // namespace autoware::universe_utils
214214

215215
#endif // AUTOWARE__UNIVERSE_UTILS__GEOMETRY__ALT_GEOMETRY_HPP_

common/autoware_universe_utils/src/geometry/alt_geometry.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ bool within(const alt::Point2d & point, const alt::Polygon2d & poly)
707707
return within(point, poly.outer());
708708
}
709709

710-
bool within(const alt::Polygon2d & poly_contained, const alt::ConvexPolygon2d & poly_containing)
710+
bool within(const alt::Polygon2d & poly_contained, const alt::Polygon2d & poly_containing)
711711
{
712712
if (equals(poly_contained, poly_containing)) {
713713
return true;
@@ -720,6 +720,14 @@ bool within(const alt::Polygon2d & poly_contained, const alt::ConvexPolygon2d &
720720
}
721721
}
722722

723+
for (const auto & inner : poly_contained.inners()) {
724+
for (const auto & vertex : inner) {
725+
if (!within(vertex, poly_containing)) {
726+
return false;
727+
}
728+
}
729+
}
730+
723731
return true;
724732
}
725733
} // namespace autoware::universe_utils

common/autoware_universe_utils/test/src/geometry/test_alt_geometry.cpp

+223-35
Original file line numberDiff line numberDiff line change
@@ -1089,61 +1089,183 @@ TEST(alt_geometry, within)
10891089
}
10901090

10911091
{ // One polygon is within the other
1092-
PointList2d vertices1;
1093-
vertices1.push_back({1.0, 1.0});
1094-
vertices1.push_back({1.0, -1.0});
1095-
vertices1.push_back({-1.0, -1.0});
1096-
vertices1.push_back({-1.0, 1.0});
1097-
1098-
PointList2d vertices2;
1099-
vertices2.push_back({2.0, 2.0});
1100-
vertices2.push_back({2.0, -2.0});
1101-
vertices2.push_back({-2.0, -2.0});
1102-
vertices2.push_back({-2.0, 2.0});
1092+
PointList2d outer_contained;
1093+
outer_contained.push_back({0.5, 0.5});
1094+
outer_contained.push_back({0.5, 1.0});
1095+
outer_contained.push_back({1.0, 0.5});
1096+
1097+
PointList2d outer_containing;
1098+
outer_containing.push_back({0.0, 0.0});
1099+
outer_containing.push_back({0.0, 2.0});
1100+
outer_containing.push_back({1.0, 1.0});
1101+
outer_containing.push_back({2.0, 2.0});
1102+
outer_containing.push_back({2.0, 0.0});
11031103

11041104
const auto result = within(
1105-
ConvexPolygon2d::create(vertices1).value(), ConvexPolygon2d::create(vertices2).value());
1105+
Polygon2d::create(outer_contained, {}).value(),
1106+
Polygon2d::create(outer_containing, {}).value());
11061107

11071108
EXPECT_TRUE(result);
11081109
}
11091110

11101111
{ // One polygon is outside the other
1111-
PointList2d vertices1;
1112-
vertices1.push_back({1.0, 1.0});
1113-
vertices1.push_back({1.0, -1.0});
1114-
vertices1.push_back({-1.0, -1.0});
1115-
vertices1.push_back({-1.0, 1.0});
1116-
1117-
PointList2d vertices2;
1118-
vertices2.push_back({3.0, 3.0});
1119-
vertices2.push_back({3.0, 2.0});
1120-
vertices2.push_back({2.0, 2.0});
1121-
vertices2.push_back({2.0, 3.0});
1112+
PointList2d outer_contained;
1113+
outer_contained.push_back({1.0, 1.0});
1114+
outer_contained.push_back({1.0, -1.0});
1115+
outer_contained.push_back({-1.0, -1.0});
1116+
outer_contained.push_back({-1.0, 1.0});
1117+
1118+
PointList2d outer_containing;
1119+
outer_containing.push_back({3.0, 3.0});
1120+
outer_containing.push_back({3.0, 2.0});
1121+
outer_containing.push_back({2.0, 2.0});
1122+
outer_containing.push_back({2.0, 3.0});
11221123

11231124
const auto result = within(
1124-
ConvexPolygon2d::create(vertices1).value(), ConvexPolygon2d::create(vertices2).value());
1125+
Polygon2d::create(outer_contained, {}).value(),
1126+
Polygon2d::create(outer_containing, {}).value());
11251127

11261128
EXPECT_FALSE(result);
11271129
}
11281130

11291131
{ // Both polygons are the same
1130-
PointList2d vertices1;
1131-
vertices1.push_back({1.0, 1.0});
1132-
vertices1.push_back({1.0, -1.0});
1133-
vertices1.push_back({-1.0, -1.0});
1134-
vertices1.push_back({-1.0, 1.0});
1132+
PointList2d outer_contained;
1133+
outer_contained.push_back({1.0, 1.0});
1134+
outer_contained.push_back({1.0, -1.0});
1135+
outer_contained.push_back({-1.0, -1.0});
1136+
outer_contained.push_back({-1.0, 1.0});
1137+
1138+
PointList2d outer_containing;
1139+
outer_containing.push_back({1.0, 1.0});
1140+
outer_containing.push_back({1.0, -1.0});
1141+
outer_containing.push_back({-1.0, -1.0});
1142+
outer_containing.push_back({-1.0, 1.0});
11351143

1136-
PointList2d vertices2;
1137-
vertices2.push_back({1.0, 1.0});
1138-
vertices2.push_back({1.0, -1.0});
1139-
vertices2.push_back({-1.0, -1.0});
1140-
vertices2.push_back({-1.0, 1.0});
1144+
const auto result = within(
1145+
Polygon2d::create(outer_contained, {}).value(),
1146+
Polygon2d::create(outer_containing, {}).value());
1147+
1148+
EXPECT_TRUE(result);
1149+
}
1150+
1151+
{ // One polygon is within the hole of the other
1152+
PointList2d outer_contained;
1153+
outer_contained.push_back({0.5, 0.5});
1154+
outer_contained.push_back({0.5, 1.0});
1155+
outer_contained.push_back({1.0, 0.5});
1156+
1157+
PointList2d outer_containing;
1158+
outer_containing.push_back({-1.0, -1.0});
1159+
outer_containing.push_back({-1.0, 3.0});
1160+
outer_containing.push_back({3.0, 3.0});
1161+
outer_containing.push_back({3.0, -1.0});
1162+
1163+
PointList2d inner_containing;
1164+
inner_containing.push_back({0.0, 0.0});
1165+
inner_containing.push_back({0.0, 2.0});
1166+
inner_containing.push_back({1.0, 1.0});
1167+
inner_containing.push_back({2.0, 2.0});
1168+
inner_containing.push_back({2.0, 0.0});
11411169

11421170
const auto result = within(
1143-
ConvexPolygon2d::create(vertices1).value(), ConvexPolygon2d::create(vertices2).value());
1171+
Polygon2d::create(outer_contained, {}).value(),
1172+
Polygon2d::create(outer_containing, {inner_containing}).value());
1173+
1174+
EXPECT_FALSE(result);
1175+
}
1176+
1177+
{ // One polygon intersects the hole of the other
1178+
PointList2d outer_contained;
1179+
outer_contained.push_back({0.5, 1.5});
1180+
outer_contained.push_back({1.5, 1.5});
1181+
outer_contained.push_back({1.5, 0.5});
1182+
outer_contained.push_back({0.5, 0.5});
1183+
1184+
PointList2d outer_containing;
1185+
outer_containing.push_back({-1.0, -1.0});
1186+
outer_containing.push_back({-1.0, 3.0});
1187+
outer_containing.push_back({3.0, 3.0});
1188+
outer_containing.push_back({3.0, -1.0});
1189+
1190+
PointList2d inner_containing;
1191+
inner_containing.push_back({0.0, 0.0});
1192+
inner_containing.push_back({0.0, 2.0});
1193+
inner_containing.push_back({1.0, 1.0});
1194+
inner_containing.push_back({2.0, 2.0});
1195+
inner_containing.push_back({2.0, 0.0});
1196+
1197+
const auto result = within(
1198+
Polygon2d::create(outer_contained, {}).value(),
1199+
Polygon2d::create(outer_containing, {inner_containing}).value());
1200+
1201+
EXPECT_FALSE(result);
1202+
}
1203+
1204+
{
1205+
// One polygon with a hole is within the other
1206+
PointList2d outer_contained;
1207+
outer_contained.push_back({-1.5, -1.5});
1208+
outer_contained.push_back({-1.5, 1.5});
1209+
outer_contained.push_back({1.5, 1.5});
1210+
outer_contained.push_back({1.5, -1.5});
1211+
1212+
PointList2d inner_contained;
1213+
inner_contained.push_back({-1.0, -1.0});
1214+
inner_contained.push_back({-1.0, 1.0});
1215+
inner_contained.push_back({1.0, 1.0});
1216+
inner_contained.push_back({1.0, -1.0});
1217+
1218+
PointList2d outer_containing;
1219+
outer_containing.push_back({-2.0, -2.0});
1220+
outer_containing.push_back({-2.0, 2.0});
1221+
outer_containing.push_back({2.0, 2.0});
1222+
outer_containing.push_back({2.0, -2.0});
1223+
1224+
PointList2d inner_containing;
1225+
inner_containing.push_back({-0.5, -0.5});
1226+
inner_containing.push_back({-0.5, 0.5});
1227+
inner_containing.push_back({0.5, 0.5});
1228+
inner_containing.push_back({0.5, -0.5});
1229+
1230+
const auto result = within(
1231+
Polygon2d::create(outer_contained, {inner_contained}).value(),
1232+
Polygon2d::create(outer_containing, {inner_containing}).value());
11441233

11451234
EXPECT_TRUE(result);
11461235
}
1236+
1237+
{
1238+
// One polygon with a hole is not within the other
1239+
PointList2d outer_contained;
1240+
outer_contained.push_back({-1.5, -1.5});
1241+
outer_contained.push_back({-1.5, 1.5});
1242+
outer_contained.push_back({1.5, 1.5});
1243+
outer_contained.push_back({1.5, -1.5});
1244+
1245+
PointList2d inner_contained;
1246+
inner_contained.push_back({-0.5, -0.5});
1247+
inner_contained.push_back({-0.5, 0.5});
1248+
inner_contained.push_back({0.5, 0.5});
1249+
inner_contained.push_back({0.5, -0.5});
1250+
1251+
PointList2d outer_containing;
1252+
outer_containing.push_back({-2.0, -2.0});
1253+
outer_containing.push_back({-2.0, 2.0});
1254+
outer_containing.push_back({2.0, 2.0});
1255+
outer_containing.push_back({2.0, -2.0});
1256+
1257+
PointList2d inner_containing;
1258+
inner_containing.push_back({-1.0, -1.0});
1259+
inner_containing.push_back({-1.0, 1.0});
1260+
inner_containing.push_back({1.0, 1.0});
1261+
inner_containing.push_back({1.0, -1.0});
1262+
1263+
const auto result = within(
1264+
Polygon2d::create(outer_contained, {inner_contained}).value(),
1265+
Polygon2d::create(outer_containing, {inner_containing}).value());
1266+
1267+
EXPECT_FALSE(result);
1268+
}
11471269
}
11481270

11491271
TEST(alt_geometry, areaRand)
@@ -1870,3 +1992,69 @@ TEST(alt_geometry, withinPolygonRand)
18701992
(alt_not_within_ns + alt_within_ns) / 1e6);
18711993
}
18721994
}
1995+
1996+
TEST(alt_geometry, withinPolygonConcaveRand)
1997+
{
1998+
std::vector<autoware::universe_utils::Polygon2d> polygons;
1999+
constexpr auto polygons_nb = 100;
2000+
constexpr auto max_vertices = 10;
2001+
constexpr auto max_values = 1000;
2002+
2003+
autoware::universe_utils::StopWatch<std::chrono::nanoseconds, std::chrono::nanoseconds> sw;
2004+
for (auto vertices = 4UL; vertices < max_vertices; ++vertices) {
2005+
double ground_truth_within_ns = 0.0;
2006+
double ground_truth_not_within_ns = 0.0;
2007+
double alt_within_ns = 0.0;
2008+
double alt_not_within_ns = 0.0;
2009+
int within_count = 0;
2010+
2011+
polygons.clear();
2012+
for (auto i = 0; i < polygons_nb; ++i) {
2013+
polygons.push_back(autoware::universe_utils::random_concave_polygon(vertices, max_values));
2014+
}
2015+
for (auto i = 0UL; i < polygons.size(); ++i) {
2016+
for (auto j = 0UL; j < polygons.size(); ++j) {
2017+
sw.tic();
2018+
const auto ground_truth = boost::geometry::within(polygons[i], polygons[j]);
2019+
if (ground_truth) {
2020+
++within_count;
2021+
ground_truth_within_ns += sw.toc();
2022+
} else {
2023+
ground_truth_not_within_ns += sw.toc();
2024+
}
2025+
2026+
const auto alt_poly1 =
2027+
autoware::universe_utils::alt::Polygon2d::create(polygons[i]).value();
2028+
const auto alt_poly2 =
2029+
autoware::universe_utils::alt::Polygon2d::create(polygons[j]).value();
2030+
sw.tic();
2031+
const auto alt = autoware::universe_utils::within(alt_poly1, alt_poly2);
2032+
if (alt) {
2033+
alt_within_ns += sw.toc();
2034+
} else {
2035+
alt_not_within_ns += sw.toc();
2036+
}
2037+
2038+
if (ground_truth != alt) {
2039+
std::cout << "Alt failed for the 2 polygons: ";
2040+
std::cout << boost::geometry::wkt(polygons[i]) << boost::geometry::wkt(polygons[j])
2041+
<< std::endl;
2042+
}
2043+
EXPECT_EQ(ground_truth, alt);
2044+
}
2045+
}
2046+
std::printf(
2047+
"polygons_nb = %d, vertices = %ld, %d / %d pairs either of which is within the other\n",
2048+
polygons_nb, vertices, within_count, polygons_nb * polygons_nb);
2049+
std::printf(
2050+
"\tWithin:\n\t\tBoost::geometry = %2.2f ms\n\t\tAlt = %2.2f ms\n",
2051+
ground_truth_within_ns / 1e6, alt_within_ns / 1e6);
2052+
std::printf(
2053+
"\tNot within:\n\t\tBoost::geometry = %2.2f ms\n\t\tAlt = %2.2f ms\n",
2054+
ground_truth_not_within_ns / 1e6, alt_not_within_ns / 1e6);
2055+
std::printf(
2056+
"\tTotal:\n\t\tBoost::geometry = %2.2f ms\n\t\tAlt = %2.2f ms\n",
2057+
(ground_truth_not_within_ns + ground_truth_within_ns) / 1e6,
2058+
(alt_not_within_ns + alt_within_ns) / 1e6);
2059+
}
2060+
}

0 commit comments

Comments
 (0)