I would suggest searching for an answer in a more generic forum, e.g., StackOverflow:
https://stackoverflow.com/search?q=determine+matrix+rotation
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~~
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
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)
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");
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; }
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.