Follow-up to previous commit (wipe tower rotation)

This commit is contained in:
Lukas Matena 2022-12-15 16:02:33 +01:00 committed by enricoturri1966
parent 58688139fd
commit 84416b41e1

View File

@ -3627,56 +3627,6 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
m_dirty = true; m_dirty = true;
} }
#if ENABLE_WORLD_COORDINATE
// This function is a replacement for function Vec3d Geometry::extract_rotation(const Transform3d& transform)
// which is returning wrong values for the call made in the following method GLCanvas3D::do_rotate() when rotating the wipe tower
Vec3d extract_rotation(const Transform3d& transform)
{
// use only the non-translational part of the transform
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> rotation_matrix = transform.matrix().block(0, 0, 3, 3);
// remove scale
rotation_matrix.col(0).normalize();
rotation_matrix.col(1).normalize();
rotation_matrix.col(2).normalize();
// reference: http://eecs.qmul.ac.uk/~gslabaugh/publications/euler.pdf
Vec3d angles1 = Vec3d::Zero();
Vec3d angles2 = Vec3d::Zero();
if (std::abs(std::abs(rotation_matrix(2, 0)) - 1.0) < 1e-5) {
angles1.z() = 0.0;
if (rotation_matrix(2, 0) < 0.0) { // == -1.0
angles1.y() = 0.5 * double(PI);
angles1.x() = angles1.z() + ::atan2(rotation_matrix(0, 1), rotation_matrix(0, 2));
}
else { // == 1.0
angles1.y() = -0.5 * double(PI);
angles1.x() = -angles1.y() + ::atan2(-rotation_matrix(0, 1), -rotation_matrix(0, 2));
}
angles2 = angles1;
}
else {
angles1.y() = -::asin(rotation_matrix(2, 0));
const double inv_cos1 = 1.0 / ::cos(angles1.y());
angles1.x() = ::atan2(rotation_matrix(2, 1) * inv_cos1, rotation_matrix(2, 2) * inv_cos1);
angles1.z() = ::atan2(rotation_matrix(1, 0) * inv_cos1, rotation_matrix(0, 0) * inv_cos1);
angles2.y() = double(PI) - angles1.y();
const double inv_cos2 = 1.0 / ::cos(angles2.y());
angles2.x() = ::atan2(rotation_matrix(2, 1) * inv_cos2, rotation_matrix(2, 2) * inv_cos2);
angles2.z() = ::atan2(rotation_matrix(1, 0) * inv_cos2, rotation_matrix(0, 0) * inv_cos2);
}
// The following euristic is the best found up to now (in the sense that it works fine with the greatest number of edge use-cases)
// but there are other use-cases were it does not
// We need to improve it
const double min_1 = angles1.cwiseAbs().minCoeff();
const double min_2 = angles2.cwiseAbs().minCoeff();
const bool use_1 = (min_1 < min_2) || (is_approx(min_1, min_2) && (angles1.norm() <= angles2.norm()));
return use_1 ? angles1 : angles2;
}
#endif // ENABLE_WORLD_COORDINATE
void GLCanvas3D::do_rotate(const std::string& snapshot_type) void GLCanvas3D::do_rotate(const std::string& snapshot_type)
{ {
if (m_model == nullptr) if (m_model == nullptr)
@ -3710,7 +3660,9 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
if (v->is_wipe_tower) { if (v->is_wipe_tower) {
const Vec3d offset = v->get_volume_offset(); const Vec3d offset = v->get_volume_offset();
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), extract_rotation(v->get_volume_transformation().get_matrix()).z()))); Vec3d rot_unit_x = v->get_volume_transformation().get_matrix().linear() * Vec3d::UnitX();
double z_rot = std::atan2(rot_unit_x.y(), rot_unit_x.x());
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), z_rot)));
#else #else
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), v->get_volume_rotation().z()))); post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), v->get_volume_rotation().z())));
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE