Tech ENABLE_TRANSFORMATIONS_BY_MATRICES - 1st installment. Geometry::Transformation modified to store data in a single matrix, without store the matrix components

Fixed conflicts during rebase with master
This commit is contained in:
enricoturri1966 2022-04-29 13:51:58 +02:00
parent a4c0d99616
commit 7e72963293
23 changed files with 9768 additions and 9095 deletions

View file

@ -313,6 +313,34 @@ Transform3d assemble_transform(const Vec3d& translation, const Vec3d& rotation,
return transform;
}
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
void rotation_transform(Transform3d& transform, const Vec3d& rotation)
{
transform = Transform3d::Identity();
transform.rotate(Eigen::AngleAxisd(rotation.z(), Vec3d::UnitZ()) * Eigen::AngleAxisd(rotation.y(), Vec3d::UnitY()) * Eigen::AngleAxisd(rotation.x(), Vec3d::UnitX()));
}
Transform3d rotation_transform(const Vec3d& rotation)
{
Transform3d transform;
rotation_transform(transform, rotation);
return transform;
}
void scale_transform(Transform3d& transform, const Vec3d& scale)
{
transform = Transform3d::Identity();
transform.scale(scale);
}
Transform3d scale_transform(const Vec3d& scale)
{
Transform3d transform;
scale_transform(transform, scale);
return transform;
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
Vec3d extract_euler_angles(const Eigen::Matrix<double, 3, 3, Eigen::DontAlign>& rotation_matrix)
{
// reference: http://eecs.qmul.ac.uk/~gslabaugh/publications/euler.pdf
@ -363,6 +391,46 @@ Vec3d extract_euler_angles(const Transform3d& transform)
return extract_euler_angles(m);
}
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
Transform3d Transformation::get_offset_matrix() const
{
return assemble_transform(get_offset());
}
static Transform3d extract_rotation(const Transform3d& trafo)
{
Matrix3d rotation;
Matrix3d scale;
trafo.computeRotationScaling(&rotation, &scale);
return Transform3d(rotation);
}
static Transform3d extract_scale(const Transform3d& trafo)
{
Matrix3d rotation;
Matrix3d scale;
trafo.computeRotationScaling(&rotation, &scale);
return Transform3d(scale);
}
static std::pair<Transform3d, Transform3d> extract_rotation_scale(const Transform3d& trafo)
{
Matrix3d rotation;
Matrix3d scale;
trafo.computeRotationScaling(&rotation, &scale);
return { Transform3d(rotation), Transform3d(scale) };
}
Vec3d Transformation::get_rotation() const
{
return extract_euler_angles(extract_rotation(m_matrix));
}
Transform3d Transformation::get_rotation_matrix() const
{
return extract_rotation(m_matrix);
}
#else
bool Transformation::Flags::needs_update(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
{
return (this->dont_translate != dont_translate) || (this->dont_rotate != dont_rotate) || (this->dont_scale != dont_scale) || (this->dont_mirror != dont_mirror);
@ -400,12 +468,19 @@ void Transformation::set_offset(Axis axis, double offset)
m_dirty = true;
}
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
void Transformation::set_rotation(const Vec3d& rotation)
{
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
const Vec3d offset = get_offset();
m_matrix = rotation_transform(rotation) * extract_scale(m_matrix);
m_matrix.translation() = offset;
#else
set_rotation(X, rotation.x());
set_rotation(Y, rotation.y());
set_rotation(Z, rotation.z());
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
}
void Transformation::set_rotation(Axis axis, double rotation)
@ -414,32 +489,106 @@ void Transformation::set_rotation(Axis axis, double rotation)
if (is_approx(std::abs(rotation), 2.0 * double(PI)))
rotation = 0.0;
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
auto [curr_rotation, scale] = extract_rotation_scale(m_matrix);
Vec3d angles = extract_euler_angles(curr_rotation);
angles[axis] = rotation;
const Vec3d offset = get_offset();
m_matrix = rotation_transform(angles) * scale;
m_matrix.translation() = offset;
#else
if (m_rotation(axis) != rotation) {
m_rotation(axis) = rotation;
m_dirty = true;
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
}
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
Vec3d Transformation::get_scaling_factor() const
{
const Transform3d scale = extract_scale(m_matrix);
return { scale(0, 0), scale(1, 1), scale(2, 2) };
}
Transform3d Transformation::get_scaling_factor_matrix() const
{
return extract_scale(m_matrix);
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
void Transformation::set_scaling_factor(const Vec3d& scaling_factor)
{
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
assert(scaling_factor.x() > 0.0 && scaling_factor.y() > 0.0 && scaling_factor.z() > 0.0);
const Vec3d offset = get_offset();
m_matrix = extract_rotation(m_matrix) * scale_transform(scaling_factor);
m_matrix.translation() = offset;
#else
set_scaling_factor(X, scaling_factor.x());
set_scaling_factor(Y, scaling_factor.y());
set_scaling_factor(Z, scaling_factor.z());
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
}
void Transformation::set_scaling_factor(Axis axis, double scaling_factor)
{
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
assert(scaling_factor > 0.0);
auto [rotation, scale] = extract_rotation_scale(m_matrix);
scale(axis, axis) = scaling_factor;
const Vec3d offset = get_offset();
m_matrix = rotation * scale;
m_matrix.translation() = offset;
#else
if (m_scaling_factor(axis) != std::abs(scaling_factor)) {
m_scaling_factor(axis) = std::abs(scaling_factor);
m_dirty = true;
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
}
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
Vec3d Transformation::get_mirror() const
{
const Transform3d scale = extract_scale(m_matrix);
return { scale(0, 0) / std::abs(scale(0, 0)), scale(1, 1) / std::abs(scale(1, 1)), scale(2, 2) / std::abs(scale(2, 2)) };
}
Transform3d Transformation::get_mirror_matrix() const
{
const Vec3d scale = get_scaling_factor();
return scale_transform({ scale.x() / std::abs(scale.x()), scale.y() / std::abs(scale.y()), scale.z() / std::abs(scale.z()) });
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
void Transformation::set_mirror(const Vec3d& mirror)
{
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
Vec3d copy(mirror);
const Vec3d abs_mirror = copy.cwiseAbs();
for (int i = 0; i < 3; ++i) {
if (abs_mirror(i) == 0.0)
copy(i) = 1.0;
else if (abs_mirror(i) != 1.0)
copy(i) /= abs_mirror(i);
}
const Vec3d curr_scale = get_scaling_factor();
const Vec3d signs = curr_scale.cwiseProduct(copy);
set_scaling_factor({
signs.x() < 0.0 ? std::abs(curr_scale.x()) * copy.x() : curr_scale.x(),
signs.y() < 0.0 ? std::abs(curr_scale.y()) * copy.y() : curr_scale.y(),
signs.z() < 0.0 ? std::abs(curr_scale.z()) * copy.z() : curr_scale.z()
});
#else
set_mirror(X, mirror.x());
set_mirror(Y, mirror.y());
set_mirror(Z, mirror.z());
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
}
void Transformation::set_mirror(Axis axis, double mirror)
@ -450,12 +599,19 @@ void Transformation::set_mirror(Axis axis, double mirror)
else if (abs_mirror != 1.0)
mirror /= abs_mirror;
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
const double curr_scale = get_scaling_factor(axis);
const double sign = curr_scale * mirror;
set_scaling_factor(axis, sign < 0.0 ? std::abs(curr_scale) * mirror : curr_scale);
#else
if (m_mirror(axis) != mirror) {
m_mirror(axis) = mirror;
m_dirty = true;
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
}
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES
void Transformation::set_from_transform(const Transform3d& transform)
{
// offset
@ -493,17 +649,38 @@ void Transformation::set_from_transform(const Transform3d& transform)
// if (!m_matrix.isApprox(transform))
// std::cout << "something went wrong in extracting data from matrix" << std::endl;
}
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
void Transformation::reset()
{
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES
m_offset = Vec3d::Zero();
m_rotation = Vec3d::Zero();
m_scaling_factor = Vec3d::Ones();
m_mirror = Vec3d::Ones();
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
m_matrix = Transform3d::Identity();
#if !ENABLE_TRANSFORMATIONS_BY_MATRICES
m_dirty = false;
#endif // !ENABLE_TRANSFORMATIONS_BY_MATRICES
}
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
Transform3d Transformation::get_matrix_no_offset() const
{
Transformation copy(*this);
copy.reset_offset();
return copy.get_matrix();
}
Transform3d Transformation::get_matrix_no_scaling_factor() const
{
Transformation copy(*this);
copy.reset_scaling_factor();
copy.reset_mirror();
return copy.get_matrix();
}
#else
const Transform3d& Transformation::get_matrix(bool dont_translate, bool dont_rotate, bool dont_scale, bool dont_mirror) const
{
if (m_dirty || m_flags.needs_update(dont_translate, dont_rotate, dont_scale, dont_mirror)) {
@ -520,6 +697,7 @@ const Transform3d& Transformation::get_matrix(bool dont_translate, bool dont_rot
return m_matrix;
}
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
Transformation Transformation::operator * (const Transformation& other) const
{
@ -533,7 +711,11 @@ Transformation Transformation::volume_to_bed_transformation(const Transformation
if (instance_transformation.is_scaling_uniform()) {
// No need to run the non-linear least squares fitting for uniform scaling.
// Just set the inverse.
#if ENABLE_TRANSFORMATIONS_BY_MATRICES
out = instance_transformation.get_matrix_no_offset().inverse();
#else
out.set_from_transform(instance_transformation.get_matrix(true).inverse());
#endif // ENABLE_TRANSFORMATIONS_BY_MATRICES
}
else if (is_rotation_ninety_degrees(instance_transformation.get_rotation())) {
// Anisotropic scaling, rotation by multiples of ninety degrees.