Skip to content

Commit 8b48840

Browse files
committed
CPatchSolver: optimization - avoid dereferencing too many times
1 parent 5f46db8 commit 8b48840

File tree

3 files changed

+58
-48
lines changed

3 files changed

+58
-48
lines changed

include/hpp/fcl/contact_patch/contact_patch_solver.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,8 @@ struct HPP_FCL_DLLAPI ContactPatchSolver {
178178

179179
/// @brief Retrieve result, adds a post-processing step if result has bigger
180180
/// size than `this->max_patch_size`.
181-
void getResult(const ContactPatch* result, ContactPatch& contact_patch) const;
181+
void getResult(const ContactPatch::Polygon* result,
182+
ContactPatch& contact_patch) const;
182183

183184
/// @return true if p inside a clipping region defined by a and b, false
184185
/// otherwise.

include/hpp/fcl/contact_patch/contact_patch_solver.hxx

+55-46
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,13 @@ void ContactPatchSolver::computePatch(const ShapeType1& s1,
135135
// Segment-Segment case
136136
// We compute the determinant; if it is non-zero, the intersection
137137
// has already been computed: it's `Contact::pos`.
138-
const Vec2f& a = this->support_set_shape1.points()[0];
139-
const Vec2f& b = this->support_set_shape1.points()[1];
138+
const SupportSet::Polygon& pts1 = this->support_set_shape1.points();
139+
const Vec2f& a = pts1[0];
140+
const Vec2f& b = pts1[1];
140141

141-
const Vec2f& c = this->support_set_shape2.points()[0];
142-
const Vec2f& d = this->support_set_shape2.points()[1];
142+
const SupportSet::Polygon& pts2 = this->support_set_shape2.points();
143+
const Vec2f& c = pts1[0];
144+
const Vec2f& d = pts2[1];
143145

144146
const FCL_REAL det =
145147
(b(0) - a(0)) * (d(1) - c(1)) >= (b(1) - a(1)) * (c(0) - d(0));
@@ -153,19 +155,20 @@ void ContactPatchSolver::computePatch(const ShapeType1& s1,
153155

154156
const Vec2f cd = (d - c);
155157
const FCL_REAL l = cd.squaredNorm();
158+
ContactPatch::Polygon& patch = contact_patch.points();
156159

157160
// Project a onto [c, d]
158161
FCL_REAL t1 = (a - c).dot(cd);
159162
t1 = (t1 >= l) ? 1.0 : ((t1 <= 0) ? 0.0 : (t1 / l));
160163
const Vec2f p1 = c + t1 * cd;
161-
contact_patch.points().emplace_back(p1);
164+
patch.emplace_back(p1);
162165

163166
// Project b onto [c, d]
164167
FCL_REAL t2 = (b - c).dot(cd);
165168
t2 = (t2 >= l) ? 1.0 : ((t2 <= 0) ? 0.0 : (t2 / l));
166169
const Vec2f p2 = c + t2 * cd;
167170
if ((p1 - p2).squaredNorm() >= eps) {
168-
contact_patch.points().emplace_back(p2);
171+
patch.emplace_back(p2);
169172
}
170173
return;
171174
}
@@ -180,70 +183,77 @@ void ContactPatchSolver::computePatch(const ShapeType1& s1,
180183
//
181184
// The Sutherland-Hodgman algorithm needs the clipper to be at least a
182185
// triangle.
183-
SupportSet* clipper = nullptr;
184-
SupportSet* current = nullptr;
185-
SupportSet* previous = &(this->support_set_buffer);
186+
SupportSet::Polygon* clipper_ptr = nullptr;
187+
SupportSet::Polygon* current_ptr = nullptr;
188+
SupportSet::Polygon* previous_ptr = &(this->support_set_buffer.points());
186189
if (support_set_shape2.size() == 2) {
187190
// Use the first shape as clipper, second as clipped.
188-
clipper = &(this->support_set_shape1);
189-
current = &(this->support_set_shape2);
191+
clipper_ptr = &(this->support_set_shape1.points());
192+
current_ptr = &(this->support_set_shape2.points());
190193
} else {
191194
// Use the second shape as clipper, first as clipped.
192-
clipper = &(this->support_set_shape2);
193-
current = &(this->support_set_shape1);
195+
clipper_ptr = &(this->support_set_shape2.points());
196+
current_ptr = &(this->support_set_shape1.points());
194197
}
195198

196-
const size_t clipper_size = clipper->points().size();
199+
const SupportSet::Polygon& clipper = *(clipper_ptr);
200+
const size_t clipper_size = clipper.size();
197201

198202
for (size_t i = 0; i < clipper_size; ++i) {
199-
const Vec2f a = clipper->point(i);
200-
const Vec2f b = clipper->point((i + 1) % clipper_size);
203+
const Vec2f a = clipper[i];
204+
const Vec2f b = clipper[(i + 1) % clipper_size];
201205

202206
// Swap current/previous
203-
SupportSet* tmp = previous;
204-
previous = current;
205-
current = tmp;
206-
207-
current->points().clear();
208-
const size_t previous_size = previous->size();
207+
SupportSet::Polygon* tmp_ptr = previous_ptr;
208+
previous_ptr = current_ptr;
209+
current_ptr = tmp_ptr;
210+
211+
const SupportSet::Polygon& previous = *(previous_ptr);
212+
SupportSet::Polygon& current = *(current_ptr);
213+
current.clear();
214+
const size_t previous_size = previous.size();
209215
for (size_t j = 0; j < previous_size; ++j) {
210-
const Vec2f vcurrent = previous->point(j);
211-
const Vec2f vnext = previous->point((j + 1) % previous_size);
216+
const Vec2f vcurrent = previous[j];
217+
const Vec2f vnext = previous[(j + 1) % previous_size];
212218
if (pointIsInsideClippingRegion(vcurrent, a, b)) {
213-
current->points().emplace_back(vcurrent);
219+
current.emplace_back(vcurrent);
214220
if (!pointIsInsideClippingRegion(vnext, a, b)) {
215221
const Vec2f p = computeLineSegmentIntersection(a, b, vcurrent, vnext);
216-
current->points().emplace_back(p);
222+
current.emplace_back(p);
217223
}
218224
} else if (pointIsInsideClippingRegion(vnext, a, b)) {
219225
const Vec2f p = computeLineSegmentIntersection(a, b, vcurrent, vnext);
220-
current->points().emplace_back(p);
226+
current.emplace_back(p);
221227
}
222228
}
223-
if (current->size() == 0) {
229+
if (current.size() == 0) {
224230
// No intersection found, the algo can early stop.
225231
break;
226232
}
227233
}
228234

229-
if (current->size() <= 1) {
235+
if (current_ptr->size() <= 1) {
230236
contact_patch.addPoint(contact.pos);
231237
return;
232238
}
233239

234-
this->getResult(current, contact_patch);
240+
this->getResult(current_ptr, contact_patch);
235241
}
236242

237243
// ============================================================================
238-
inline void ContactPatchSolver::getResult(const ContactPatch* result,
239-
ContactPatch& contact_patch) const {
244+
inline void ContactPatchSolver::getResult(
245+
const ContactPatch::Polygon* result_ptr,
246+
ContactPatch& contact_patch) const {
240247
assert(this->max_patch_size > 3);
241-
if (result->size() <= this->max_patch_size) {
242-
contact_patch.points().emplace_back(result->points()[0]);
243-
for (size_t i = 1; i < result->size(); ++i) {
244-
if ((contact_patch.points().back() - result->points()[i]).squaredNorm() >
248+
const ContactPatch::Polygon& result = *(result_ptr);
249+
ContactPatch::Polygon& patch = contact_patch.points();
250+
251+
if (result.size() <= this->max_patch_size) {
252+
patch.emplace_back(result[0]);
253+
for (size_t i = 1; i < result.size(); ++i) {
254+
if ((patch.back() - result[i]).squaredNorm() >
245255
Eigen::NumTraits<FCL_REAL>::dummy_precision()) {
246-
contact_patch.points().emplace_back(result->points()[i]);
256+
patch.emplace_back(result[i]);
247257
}
248258
}
249259
return;
@@ -253,29 +263,28 @@ inline void ContactPatchSolver::getResult(const ContactPatch* result,
253263
// contact patch.
254264
// We simply select `max_patch_size` points of the patch by sampling the
255265
// 2d support function of the patch along the unit circle.
256-
this->added_to_patch.assign(result->size(), false);
266+
this->added_to_patch.assign(result.size(), false);
257267
const FCL_REAL angle_increment =
258268
2.0 * (FCL_REAL)(EIGEN_PI) / ((FCL_REAL)(this->max_patch_size));
259269
for (size_t i = 0; i < this->max_patch_size; ++i) {
260270
const FCL_REAL theta = (FCL_REAL)(i)*angle_increment;
261271
const Vec2f dir(std::cos(theta), std::sin(theta));
262-
FCL_REAL support_val = result->points()[0].dot(dir);
272+
FCL_REAL support_val = result[0].dot(dir);
263273
size_t support_idx = 0;
264-
for (size_t j = 1; j < result->size(); ++j) {
265-
const FCL_REAL val = result->points()[j].dot(dir);
274+
for (size_t j = 1; j < result.size(); ++j) {
275+
const FCL_REAL val = result[j].dot(dir);
266276
if (val > support_val) {
267277
support_val = val;
268278
support_idx = j;
269279
}
270280
}
271281
if (!this->added_to_patch[support_idx]) {
272-
if (contact_patch.points().empty()) {
273-
contact_patch.points().emplace_back(result->points()[support_idx]);
282+
if (patch.empty()) {
283+
patch.emplace_back(result[support_idx]);
274284
} else {
275-
if ((contact_patch.points().back() - result->points()[support_idx])
276-
.squaredNorm() >
285+
if ((patch.back() - result[support_idx]).squaredNorm() >
277286
Eigen::NumTraits<FCL_REAL>::dummy_precision()) {
278-
contact_patch.points().emplace_back(result->points()[support_idx]);
287+
patch.emplace_back(result[support_idx]);
279288
}
280289
}
281290
this->added_to_patch[support_idx] = true;

include/hpp/fcl/internal/shape_shape_contact_patch_func.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ void computePatchPlaneOrHalfspace(const OtherShapeType& s1,
129129
&s1, support_set, csolver->support_guess[0], csolver->supports_data[0],
130130
csolver->num_samples_curved_shapes, csolver->patch_tolerance);
131131
}
132-
csolver->getResult(&support_set, contact_patch);
132+
csolver->getResult(&(support_set.points()), contact_patch);
133133
}
134134

135135
#define PLANE_OR_HSPACE_AND_OTHER_SHAPE_CONTACT_PATCH(PlaneOrHspace) \

0 commit comments

Comments
 (0)