Skip to content

Commit 0f01669

Browse files
authored
Merge pull request #27 from leggedrobotics/fix/merge_edge_loops
merge 3 loops around edges into 1
2 parents c91e01e + 42fb80c commit 0f01669

File tree

2 files changed

+82
-37
lines changed

2 files changed

+82
-37
lines changed

plane_segmentation/convex_plane_decomposition/include/convex_plane_decomposition/ConvexRegionGrowing.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@ CgalPolygon2d growConvexPolygonInsideShape(const CgalPolygon2d& parentShape, Cga
1515
CgalPolygon2d growConvexPolygonInsideShape(const CgalPolygonWithHoles2d& parentShape, CgalPoint2d center, int numberOfVertices,
1616
double growthFactor);
1717

18-
template <typename T>
19-
bool pointCanBeMoved(const CgalPolygon2d& growthShape, int i, const CgalPoint2d& candidatePoint, CgalCircle2d& freeSphere,
20-
const T& parentShape);
21-
2218
void updateMean(CgalPoint2d& mean, const CgalPoint2d& oldValue, const CgalPoint2d& updatedValue, int N);
2319

2420
} // namespace convex_plane_decomposition

plane_segmentation/convex_plane_decomposition/src/ConvexRegionGrowing.cpp

Lines changed: 82 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,7 @@
88

99
namespace convex_plane_decomposition {
1010

11-
CgalPolygon2d createRegularPolygon(const CgalPoint2d& center, double radius, int numberOfVertices) {
12-
assert(numberOfVertices > 2);
13-
CgalPolygon2d polygon;
14-
polygon.container().reserve(numberOfVertices);
15-
double angle = (2. * M_PI) / numberOfVertices;
16-
for (int i = 0; i < numberOfVertices; ++i) {
17-
double phi = i * angle;
18-
double px = radius * std::cos(phi) + center.x();
19-
double py = radius * std::sin(phi) + center.y();
20-
// Counter clockwise
21-
polygon.push_back({px, py});
22-
}
23-
return polygon;
24-
}
11+
namespace {
2512

2613
int getCounterClockWiseNeighbour(int i, int lastVertex) {
2714
return (i > 0) ? i - 1 : lastVertex;
@@ -31,12 +18,6 @@ int getClockWiseNeighbour(int i, int lastVertex) {
3118
return (i < lastVertex) ? i + 1 : 0;
3219
}
3320

34-
void updateMean(CgalPoint2d& mean, const CgalPoint2d& oldValue, const CgalPoint2d& updatedValue, int N) {
35-
// old_mean = 1/N * ( others + old_value); -> others = N*old_mean - old_value
36-
// new_mean = 1/N * ( others + new_value); -> new_mean = old_mean - 1/N * oldValue + 1/N * updatedValue
37-
mean += 1.0 / N * (updatedValue - oldValue);
38-
}
39-
4021
std::array<CgalPoint2d, 2> getNeighbours(const CgalPolygon2d& polygon, int i) {
4122
assert(i < polygon.size());
4223
assert(polygon.size() > 1);
@@ -75,6 +56,55 @@ bool pointAndNeighboursAreWithinFreeSphere(const std::array<CgalPoint2d, 2>& nei
7556
return isInside(neighbours[0], circle) && isInside(point, circle) && isInside(neighbours[1], circle);
7657
}
7758

59+
/**
60+
* Returns {true, 0.0} if either one of the point -> neighbour segments intersects the parent shape
61+
* Returns {false, minSquareDistance} if none of the segments intersects. minSquareDistance is the minimum square distance between the
62+
* point and the parent shape
63+
*/
64+
template <typename T>
65+
std::pair<bool, double> doEdgesIntersectAndSquareDistance(const std::array<CgalPoint2d, 2>& neighbours, const CgalPoint2d& point,
66+
const T& parentShape);
67+
68+
template <>
69+
std::pair<bool, double> doEdgesIntersectAndSquareDistance(const std::array<CgalPoint2d, 2>& neighbours, const CgalPoint2d& point,
70+
const CgalPolygon2d& parentShape) {
71+
CgalSegment2d segment0{neighbours[0], point};
72+
CgalSegment2d segment1{neighbours[1], point};
73+
74+
double minDistSquared = std::numeric_limits<double>::max();
75+
for (auto edgeIt = parentShape.edges_begin(); edgeIt != parentShape.edges_end(); ++edgeIt) {
76+
const auto edge = *edgeIt;
77+
if (CGAL::do_intersect(segment0, edge) || CGAL::do_intersect(segment1, edge)) {
78+
return {true, 0.0};
79+
} else {
80+
minDistSquared = std::min(minDistSquared, CGAL::squared_distance(point, edge));
81+
}
82+
}
83+
84+
return {false, minDistSquared};
85+
}
86+
87+
template <>
88+
std::pair<bool, double> doEdgesIntersectAndSquareDistance(const std::array<CgalPoint2d, 2>& neighbours, const CgalPoint2d& point,
89+
const CgalPolygonWithHoles2d& parentShape) {
90+
const auto intersectAndDistance = doEdgesIntersectAndSquareDistance(neighbours, point, parentShape.outer_boundary());
91+
if (intersectAndDistance.first) {
92+
return {true, 0.0};
93+
}
94+
95+
double minDistSquared = intersectAndDistance.second;
96+
for (const auto& hole : parentShape.holes()) {
97+
const auto holeIntersectAndDistance = doEdgesIntersectAndSquareDistance(neighbours, point, hole);
98+
if (holeIntersectAndDistance.first) {
99+
return {true, 0.0};
100+
} else {
101+
minDistSquared = std::min(minDistSquared, holeIntersectAndDistance.second);
102+
}
103+
}
104+
105+
return {false, minDistSquared};
106+
}
107+
78108
template <typename T>
79109
bool pointCanBeMoved(const CgalPolygon2d& growthShape, int i, const CgalPoint2d& candidatePoint, CgalCircle2d& freeSphere,
80110
const T& parentShape) {
@@ -83,25 +113,22 @@ bool pointCanBeMoved(const CgalPolygon2d& growthShape, int i, const CgalPoint2d&
83113
if (pointAndNeighboursAreWithinFreeSphere(neighbours, candidatePoint, freeSphere)) {
84114
return true;
85115
} else {
86-
// Update free sphere around new point
87-
freeSphere = CgalCircle2d(candidatePoint, squaredDistance(candidatePoint, parentShape));
88-
CgalSegment2d segment0{neighbours[0], candidatePoint};
89-
CgalSegment2d segment1{neighbours[1], candidatePoint};
90-
91-
bool segment0IsFree = isInside(neighbours[0], freeSphere) || !doEdgesIntersect(segment0, parentShape);
92-
if (segment0IsFree) {
93-
bool segment1IsFree = isInside(neighbours[1], freeSphere) || !doEdgesIntersect(segment1, parentShape);
94-
return segment1IsFree;
95-
} else {
116+
// Look for intersections and minimum distances simultaneously
117+
const auto intersectAndDistance = doEdgesIntersectAndSquareDistance(neighbours, candidatePoint, parentShape);
118+
119+
if (intersectAndDistance.first) {
96120
return false;
121+
} else {
122+
// Update free sphere around new point
123+
freeSphere = CgalCircle2d(candidatePoint, intersectAndDistance.second);
124+
return true;
97125
}
98126
}
99127
} else {
100128
return false;
101129
}
102130
}
103131

104-
namespace {
105132
inline std::ostream& operator<<(std::ostream& os, const CgalPolygon2d& p) {
106133
os << "CgalPolygon2d: \n";
107134
for (auto it = p.vertices_begin(); it != p.vertices_end(); ++it) {
@@ -119,7 +146,6 @@ inline std::ostream& operator<<(std::ostream& os, const CgalPolygonWithHoles2d&
119146
}
120147
return os;
121148
}
122-
} // namespace
123149

124150
template <typename T>
125151
CgalPolygon2d growConvexPolygonInsideShape_impl(const T& parentShape, CgalPoint2d center, int numberOfVertices, double growthFactor) {
@@ -164,10 +190,26 @@ CgalPolygon2d growConvexPolygonInsideShape_impl(const T& parentShape, CgalPoint2
164190
std::cerr << "Center: " << centerCopy.x() << ", " << centerCopy.y() << "\n";
165191
std::cerr << parentShape << "\n";
166192
}
167-
168193
return growthShape;
169194
}
170195

196+
} // namespace
197+
198+
CgalPolygon2d createRegularPolygon(const CgalPoint2d& center, double radius, int numberOfVertices) {
199+
assert(numberOfVertices > 2);
200+
CgalPolygon2d polygon;
201+
polygon.container().reserve(numberOfVertices);
202+
double angle = (2. * M_PI) / numberOfVertices;
203+
for (int i = 0; i < numberOfVertices; ++i) {
204+
double phi = i * angle;
205+
double px = radius * std::cos(phi) + center.x();
206+
double py = radius * std::sin(phi) + center.y();
207+
// Counter clockwise
208+
polygon.push_back({px, py});
209+
}
210+
return polygon;
211+
}
212+
171213
CgalPolygon2d growConvexPolygonInsideShape(const CgalPolygon2d& parentShape, CgalPoint2d center, int numberOfVertices,
172214
double growthFactor) {
173215
return growConvexPolygonInsideShape_impl(parentShape, center, numberOfVertices, growthFactor);
@@ -177,4 +219,11 @@ CgalPolygon2d growConvexPolygonInsideShape(const CgalPolygonWithHoles2d& parentS
177219
double growthFactor) {
178220
return growConvexPolygonInsideShape_impl(parentShape, center, numberOfVertices, growthFactor);
179221
}
222+
223+
void updateMean(CgalPoint2d& mean, const CgalPoint2d& oldValue, const CgalPoint2d& updatedValue, int N) {
224+
// old_mean = 1/N * ( others + old_value); -> others = N*old_mean - old_value
225+
// new_mean = 1/N * ( others + new_value); -> new_mean = old_mean - 1/N * oldValue + 1/N * updatedValue
226+
mean += 1.0 / N * (updatedValue - oldValue);
227+
}
228+
180229
} // namespace convex_plane_decomposition

0 commit comments

Comments
 (0)