在Revit API中,我试图用“机械设备”类别的几乎相同版本替换“特殊设备”类别的族实例。到目前为止,我已经能够将新实例与旧实例插入相同的位置,但是我无法匹配相同的方向。 FamilyInstance
有一种方法GetTransform
,我可以用它来获得旧Transform
的{{1}},但是没有方法FamilyInstance
来设置新的SetTransform
。唯一可用于移动新FamilyInstance
的工具是FamilyInstance
,其功能类似于ElementTransformUtils
和MoveElement
,但我不确定使用旧的{{1 }}。
如何确保新RotateElement
的方向与旧Transform
的方向匹配?
答案 0 :(得分:1)
在Wikipedia中检查how to determine the axis and the angle of rotation后,我能够为此编写代码。我还必须抬头how to calculate the trace才能确定角度。
private static Line GetRotationAxisFromTransform(Transform transform)
{
double x = transform.BasisY.Z - transform.BasisZ.Y;
double y = transform.BasisZ.X - transform.BasisX.Z;
double z = transform.BasisX.Y - transform.BasisY.X;
return Line.CreateUnbound(transform.Origin, new XYZ(x, y, z));
}
private static double GetRotationAngleFromTransform(Transform transform)
{
double x = transform.BasisX.X;
double y = transform.BasisY.Y;
double z = transform.BasisZ.Z;
double trace = x + y + z;
return Math.Acos((trace - 1) / 2.0);
}
然后我将它们传递到ElementTransformUtils.RotateElement
方法中,以便将FamilyInstance
#2旋转到与FamilyInstance
#1相同的位置。
答案 1 :(得分:1)
我找到了解决0或180度旋转的更好解决方案。我的第一个解决方案在这种情况下不起作用。我在euclideanspace.com找到了解决方案和代码的Java版本。
这是我的代码从Transform
获取矩阵,然后调用该函数以获取轴和角度。
double[][] matrix = new double[][]
{
new double[]{ oldTransform.BasisX.X, oldTransform.BasisY.X, oldTransform.BasisZ.X },
new double[]{ oldTransform.BasisX.Y, oldTransform.BasisY.Y, oldTransform.BasisZ.Y },
new double[]{ oldTransform.BasisX.Z, oldTransform.BasisY.Z, oldTransform.BasisZ.Z }
};
GetAxisAngleFromMatrix(matrix, out double angleOfRotation, out XYZ axisOfRotation);
Line rotationLine = Line.CreateUnbound(oldTransform.Origin, axisOfRotation);
这是数学函数
public void GetAxisAngleFromMatrix(double[][] m, out double angleOfRotation, out XYZ axisOfRotation)
{
double angle, x, y, z; // variables for result
double epsilon = 0.01; // margin to allow for rounding errors
double epsilon2 = 0.1; // margin to distinguish between 0 and 180 degrees
// optional check that input is pure rotation, 'isRotationMatrix' is defined at:
// https://www.euclideanspace.com/maths/algebra/matrix/orthogonal/rotation/
if ((Math.Abs(m[0][1] - m[1][0]) < epsilon)
&& (Math.Abs(m[0][2] - m[2][0]) < epsilon)
&& (Math.Abs(m[1][2] - m[2][1]) < epsilon))
{
// singularity found
// first check for identity matrix which must have +1 for all terms
// in leading diagonaland zero in other terms
if ((Math.Abs(m[0][1] + m[1][0]) < epsilon2)
&& (Math.Abs(m[0][2] + m[2][0]) < epsilon2)
&& (Math.Abs(m[1][2] + m[2][1]) < epsilon2)
&& (Math.Abs(m[0][0] + m[1][1] + m[2][2] - 3) < epsilon2))
{
// this singularity is identity matrix so angle = 0
angleOfRotation = 0;
axisOfRotation = new XYZ(1, 0, 0);
return;
}
// otherwise this singularity is angle = 180
angle = Math.PI;
double xx = (m[0][0] + 1) / 2;
double yy = (m[1][1] + 1) / 2;
double zz = (m[2][2] + 1) / 2;
double xy = (m[0][1] + m[1][0]) / 4;
double xz = (m[0][2] + m[2][0]) / 4;
double yz = (m[1][2] + m[2][1]) / 4;
if ((xx > yy) && (xx > zz))
{ // m[0][0] is the largest diagonal term
if (xx < epsilon)
{
x = 0;
y = 0.7071;
z = 0.7071;
}
else
{
x = Math.Sqrt(xx);
y = xy / x;
z = xz / x;
}
}
else if (yy > zz)
{ // m[1][1] is the largest diagonal term
if (yy < epsilon)
{
x = 0.7071;
y = 0;
z = 0.7071;
}
else
{
y = Math.Sqrt(yy);
x = xy / y;
z = yz / y;
}
}
else
{ // m[2][2] is the largest diagonal term so base result on this
if (zz < epsilon)
{
x = 0.7071;
y = 0.7071;
z = 0;
}
else
{
z = Math.Sqrt(zz);
x = xz / z;
y = yz / z;
}
}
angleOfRotation = angle;
axisOfRotation = new XYZ(x, y, z); // return 180 deg rotation
return;
}
// as we have reached here there are no singularities so we can handle normally
double s = Math.Sqrt((m[2][1] - m[1][2]) * (m[2][1] - m[1][2])
+ (m[0][2] - m[2][0]) * (m[0][2] - m[2][0])
+ (m[1][0] - m[0][1]) * (m[1][0] - m[0][1])); // used to normalise
if (Math.Abs(s) < 0.001) s = 1;
// prevent divide by zero, should not happen if matrix is orthogonal and should be
// caught by singularity test above, but I've left it in just in case
angle = Math.Acos((m[0][0] + m[1][1] + m[2][2] - 1) / 2);
x = (m[2][1] - m[1][2]) / s;
y = (m[0][2] - m[2][0]) / s;
z = (m[1][0] - m[0][1]) / s;
angleOfRotation = angle;
axisOfRotation = new XYZ(x, y, z);
}