Skip to content

[GetGlobalPlacement] Issue with the scale computation #159

Open

Description

@galou

The macro return the wrong result for an object with rotation 0.45642222410108496, 0.49809724456331667, 0.5849212871934979, -0.4488262203714842. The returned scale factor is -1, -1, 1 but should be 1, 1, 1. According to this, the scale computation involves the eigenvalue decomposition.

I already fixed the issue for objects that are not scaled in 47dbb41. The issue subsists for scaled objects but a warning is printed.

I added a test for this.

@Jolbas do you have the capacity to have a look at this?

Activity

  1. galou commented on Feb 27, 2023

    @galou
    CollaboratorAuthor

    Maybe a solution, given a Matrix m with rotation and scaling, Rotation(m).toMatrix().inverse() * m returns a matrix whose diagonal elements are the scaling factors. The method is not very accurate though (+/- 0.0003) and I don't know how generic it is.

  2. Jolbas commented on Feb 27, 2023

    @Jolbas
    Contributor

    I don't know how to do the polar decomposition yet. But I know for sure there is no way to distinguish between a matrix representing no scaling at all and one that is a combination of scale(-1,-1,1) and a rotation of 180 degrees. Only option is to assume that all scale factors have the same sign. There is work going on to fix related issues in the creation of a rotation from a matrix. Maybe following code will work for now.

        return_type_link_matrix = 6  # Cf. DocumentObjectPyImp.cpp::getSubObject (l.417).
        matrix = object.getSubObject(subobject_fullpath, return_type_link_matrix,
                                     transform=True)
        if matrix is None:
            return
        scale_type = matrix.hasScale(1e-7)
        if scale_type == ScaleType.Other:
            app.Console.PrintWarning('Too complex transformation to find rotation\n')
            return
        if scale_type == app.ScaleType.NoScaling:
            return app.Placement(matrix), app.Vector(1.0, 1.0, 1.0)
        position = matrix.col(3)
        matrix.setCol(3, app.Vector())
        scale_type = matrix.hasScale(1e-5)
        if scale_type == ScaleType.NonUniformRight:
            matrix.transpose()
        scale_vec = App.Vector(*(m.row(i).Length for i in range(3)))
        matrix.scale(*(1 / s for s in scale_vec))
        if scale_type == ScaleType.NonUniformRight:
            matrix.transpose()
        if matrix.determinant() < 0:
            matrix.scale(-1)
            scale_vec *= -1
        matrix.setCol(3, position)
        return app.Placement(matrix), scale_vec
    
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions