Allow AngleAxisRotatePoint to be applied in-place Thanks to @CatInTheRain for the suggestion. Fixes #1163 Change-Id: I4e148c62891979e1ec01b91f95d3e2d04501c8ef
diff --git a/include/ceres/rotation.h b/include/ceres/rotation.h index 261d3a0..c04278e 100644 --- a/include/ceres/rotation.h +++ b/include/ceres/rotation.h
@@ -282,8 +282,7 @@ // y = R(angle_axis) * x; // -// Inplace rotation is not supported. pt and result must point to different -// memory locations, otherwise the result will be undefined. +// Inplace rotation is supported. template <typename T> inline void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], @@ -791,9 +790,10 @@ inline void AngleAxisRotatePoint(const T angle_axis[3], const T pt[3], T result[3]) { - DCHECK_NE(pt, result) << "Inplace rotation is not supported."; + using std::cos; using std::fpclassify; using std::hypot; + using std::sin; const T theta = hypot(angle_axis[0], angle_axis[1], angle_axis[2]);
diff --git a/internal/ceres/rotation_test.cc b/internal/ceres/rotation_test.cc index 0dfcf71..85c8b78 100644 --- a/internal/ceres/rotation_test.cc +++ b/internal/ceres/rotation_test.cc
@@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2023 Google Inc. All rights reserved. +// Copyright 2025 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -1732,18 +1732,22 @@ rotation_matrix_rotated_p[1] = R[1] * p[0] + R[4] * p[1] + R[7] * p[2]; rotation_matrix_rotated_p[2] = R[2] * p[0] + R[5] * p[1] + R[8] * p[2]; - AngleAxisRotatePoint(angle_axis, p, angle_axis_rotated_p); - for (int k = 0; k < 3; ++k) { - // clang-format off - EXPECT_NEAR(rotation_matrix_rotated_p[k], - angle_axis_rotated_p[k], - kTolerance) << "p: " << p[0] - << " " << p[1] - << " " << p[2] - << " angle_axis: " << angle_axis[0] - << " " << angle_axis[1] - << " " << angle_axis[2]; - // clang-format on + // Rotate point and write the result to a different and the same + // destination + for (double* const dst : {angle_axis_rotated_p, angle_axis}) { + AngleAxisRotatePoint(angle_axis, p, dst); + for (int k = 0; k < 3; ++k) { + // clang-format off + EXPECT_NEAR(rotation_matrix_rotated_p[k], + dst[k], + kTolerance) << "p: " << p[0] + << " " << p[1] + << " " << p[2] + << " angle_axis: " << angle_axis[0] + << " " << angle_axis[1] + << " " << angle_axis[2]; + // clang-format on + } } } } @@ -1790,18 +1794,22 @@ rotation_matrix_rotated_p[1] = R[1] * p[0] + R[4] * p[1] + R[7] * p[2]; rotation_matrix_rotated_p[2] = R[2] * p[0] + R[5] * p[1] + R[8] * p[2]; - AngleAxisRotatePoint(angle_axis, p, angle_axis_rotated_p); - for (int k = 0; k < 3; ++k) { - // clang-format off - EXPECT_NEAR(rotation_matrix_rotated_p[k], - angle_axis_rotated_p[k], - kTolerance) << "p: " << p[0] - << " " << p[1] - << " " << p[2] - << " angle_axis: " << angle_axis[0] - << " " << angle_axis[1] - << " " << angle_axis[2]; - // clang-format on + // Rotate point and write the result to a different and the same + // destination + for (double* const dst : {angle_axis_rotated_p, angle_axis}) { + AngleAxisRotatePoint(angle_axis, p, dst); + for (int k = 0; k < 3; ++k) { + // clang-format off + EXPECT_NEAR(rotation_matrix_rotated_p[k], + dst[k], + kTolerance) << "p: " << p[0] + << " " << p[1] + << " " << p[2] + << " angle_axis: " << angle_axis[0] + << " " << angle_axis[1] + << " " << angle_axis[2]; + // clang-format on + } } } }