How to determine if the matrix contains rotation?

How to determine if the matrix contains rotation?

Anonymous
Not applicable
951 Views
11 Replies
Message 1 of 12

How to determine if the matrix contains rotation?

Anonymous
Not applicable

Transform does not seem to have this property defined.

0 Likes
952 Views
11 Replies
Replies (11)
Message 2 of 12

jeremy_tammik
Alumni
Alumni

I would suggest searching for an answer in a more generic forum, e.g., StackOverflow:

https://stackoverflow.com/search?q=determine+matrix+rotation 

 

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 3 of 12

KM_Yotsuha
Advocate
Advocate

when rotation only happens in xy plan,If the transform's BasisX is not  of same direction of XYZ.BasisX,then it is rotated. you can even computer the rotate angle,it is same as the angle between BasisX of local and globle coordinate~~

in 3d spaces,compare all basis~~

Message 4 of 12

Anonymous
Not applicable
It's not rigorous. I considered this approach a long time ago and have been thinking about it again recently. As a simple example, the scaling matrix and the mirror matrix may BaseX, BaseY, BaseZ may all change. So I say we should provide a property to determine that. So basically it is very difficult to determine because it is likely to be a composite matrix and difficult to infer.
0 Likes
Message 5 of 12

jeremy_tammik
Alumni
Alumni

This is actually a quite common task in computer graphics. Search for the term 'matrix decomposition':

  

https://duckduckgo.com/?q=matrix+decomposition

  

The Building Coder discussed it in 2009:

  

https://thebuildingcoder.typepad.com/blog/2009/05/transform-an-element.html

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 6 of 12

mhannonQ65N2
Collaborator
Collaborator

Of the top of my head, to determine if the matrix has rotation vs just reflection you could still compare the basis vectors like @KM_Yotsuha suggested but you should check if the matrix's basis vectors are in the same or opposite direction. One way of doing this is to check if the matrix's basis vector is a scalar multiple of the standard basis vector, by ensuring that only one of its components (for basis x, check the x component, etc.) is non-zero. You can also check if it has a reflection by using the HasReflection property.  Alternatively, if you want to check if it is just a rotation and possibly a translation, you can check if it's determinant is equal to one as all rotation matrices have a determinant of one (note that the identity matrix also has a determinant of one and is technically considered a rotation matrix).

 

(Note: Make sure to take floating-point precision into account, instead of checking if something is zero, check if its absolute value is less than or equal to Revit's precision value, which is 1e-9 if I recall correctly)

Message 7 of 12

ricaun
Advisor
Advisor

The Transform class has the method AlmostEqual to compare two transforms with a tolerance 1e-9.

 

Could be used to compare only the Rotation matrix if the Scale and the Origin are removed.

 

Some methods like this:

/// <summary>
/// Determines whether this transformation and the specified transformation are the 
/// same rotation within the tolerance (1.0e-09).
/// </summary>
/// <param name="left">The first transformation.</param>
/// <param name="right">The second transformation.</param>
/// <returns>True if the two transformations rotation are equal; otherwise, false.</returns>
public bool AlmostEqualRotation(Transform left, Transform right)
{
    var tLeft = left.ScaleBasis(1 / left.Scale);
    var tRight = right.ScaleBasis(1 / right.Scale);
    tLeft.Origin = XYZ.Zero;
    tRight.Origin = XYZ.Zero;
    return tLeft.AlmostEqual(tRight);
}

 

And here are some tests to validate the method:

Debug.Assert(AlmostEqualRotation(Transform.Identity, Transform.Identity), "Identity");
Debug.Assert(AlmostEqualRotation(Transform.Identity, Transform.CreateTranslation(XYZ.BasisX)), "CreateTranslation");
Debug.Assert(AlmostEqualRotation(Transform.Identity, Transform.CreateRotation(XYZ.BasisZ, 0)), "CreateRotation");
Debug.Assert(AlmostEqualRotation(Transform.Identity, Transform.Identity.ScaleBasis(2)), "ScaleBasis");

Debug.Assert(!AlmostEqualRotation(Transform.Identity, Transform.CreateRotation(XYZ.BasisZ, 1)), "!CreateRotation");

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 8 of 12

Anonymous
Not applicable

Maybe it should be the following code, but I don't seem to be reading too much into it. Not very good at math, not sure how to tell which ones are contained after the composite matrix is split.

 

https://github.com/accord-net/framework/wiki/Mathematics

 

// Singular value decomposition
{
    SingularValueDecomposition svd = new SingularValueDecomposition(A);
    var U = svd.LeftSingularVectors;
    var S = svd.Diagonal;
    var V = svd.RightSingularVectors;
}
// or (please see documentation for details)
{
    SingularValueDecomposition svd = new SingularValueDecomposition(A.Transpose());
    var U = svd.RightSingularVectors;
    var S = svd.Diagonal;
    var V = svd.LeftSingularVectors;
}

// Eigenvalue decomposition
{
    EigenvalueDecomposition eig = new EigenvalueDecomposition(A);
    var V = eig.Eigenvectors;
    var D = eig.DiagonalMatrix;
}

// QR decomposition
{
    QrDecomposition qr = new QrDecomposition(A);
    var Q = qr.OrthogonalFactor;
    var R = qr.UpperTriangularFactor;
}

// Cholesky decomposition
{
    CholeskyDecomposition chol = new CholeskyDecomposition(A);
    var R = chol.LeftTriangularFactor;
}

// LU decomposition
{
    LuDecomposition lu = new LuDecomposition(A);
    var L = lu.LowerTriangularFactor;
    var U = lu.UpperTriangularFactor;
} 

 

Message 9 of 12

mhannonQ65N2
Collaborator
Collaborator

I don't think that those decompositions will be of much use to you. Though perhaps with the QR decomposition, you could check if the orthogonal factor has a determinant of 1; if so, it is a rotation matrix and I think your original matrix contains a rotation. But I'm not too sure this will work and you'd have to convert Revit's Transform into an Accord.net matrix.

 

I'd recommend just sticking to comparing the basis vectors. Here's an example:

const double p = 1e-9;
Transform t;
// ...
var isScaleX = Math.Abs(t.BasisX.X) > p && Math.Abs(t.BasisX.Y) < p && Math.Abs(t.BasisX.Z) < p;
var isScaleY = Math.Abs(t.BasisY.X) < p && Math.Abs(t.BasisY.Y) > p && Math.Abs(t.BasisY.Z) < p;
var isScaleZ = Math.Abs(t.BasisZ.X) < p && Math.Abs(t.BasisZ.Y) < Z && Math.Abs(t.BasisZ.Z) > p;

var isRotation = !(isScaleX && isScaleY && isScaleZ);

This should be sufficient unless you are working with some transformation I wouldn't expect to find in Revit like a shear mapping.

0 Likes
Message 10 of 12

Anonymous
Not applicable

The composite matrix is obviously not very suitable for judging with it.

0 Likes
Message 11 of 12

Anonymous
Not applicable
The composite matrix is obviously not very suitable for judging with it.
0 Likes
Message 12 of 12

Anonymous
Not applicable

The main reason for discussing this issue is that the API does not provide this property or method.

0 Likes