Follow-up to previous commit (wipe tower rotation)
This commit is contained in:
parent
58688139fd
commit
84416b41e1
@ -3627,56 +3627,6 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
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)
|
||||
{
|
||||
if (m_model == nullptr)
|
||||
@ -3710,7 +3660,9 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||
if (v->is_wipe_tower) {
|
||||
const Vec3d offset = v->get_volume_offset();
|
||||
#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
|
||||
post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset.x(), offset.y(), v->get_volume_rotation().z())));
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
|
Loading…
Reference in New Issue
Block a user