给定一条任意反射线,你如何用矩阵反映一组点?我尝试了以下但我无法让它工作:
翻译系统,使反射线的P1位于 原点
旋转系统,使反射线平行于Y
轴
执行Y轴反射
撤消轮播
Iam试图在C#中为我编写一个方法来执行此操作,基本上我给它了2行,我得到了矩阵。
答案 0 :(得分:1)
there is a formula for reflecting about any line through the origin后不需要轮换。让(a,b)
和(c,d)
在反射线上任意两个点。假设您想要反映的是(x,y)
。
(a,b)
成为原点。然后(x,y)
变为(x-a,y-b)
。这一步只是矢量减法。(a,b)
添加到步骤2的结果中。步骤2的矩阵是:
H(θ) = [cos(2θ) sin(2θ)]
[sin(2θ) -cos(2θ)]
在矩阵中,θ是(平移的)反射线与正x轴形成的角度。只要a
和c
不相等,您就可以通过评估来找到θ
θ = arctangent( (d-b) / (c-a) )
您将获得严格在-π/2
和π/2
之间的值。如果a = c
,即反射线是垂直的,那么只需取θ = π/2
。虽然如果反射线是垂直的(或水平的,在这种情况下是θ = 0
),那么你可以使用众所周知的反射矩阵来反射y轴或x轴。
这几乎列出了查找和使用矩阵的整个过程。听起来你所要求的就是找到反射矩阵。我不太清楚C#在答案中使用它,但这里是伪代码:
// (a,b) and (c,d) are any two distinct points on the reflection line
getMatrix(double a, double b, double c, double d)
double x11, x12, x21, x22; // Elements of the reflection matrix
if a == c // If the reflection line is vertical
x11 = -1; x12 = 0; x21 = 0; x22 = 1;
else if b == d // If the reflection line is horizontal
x11 = 1; x12 = 0; x21 = 0; x22 = -1;
else
double θ = arctangent( (d-b) / (c-a) );
x11 = cos(2 * θ);
x12 = sin(2 * θ);
x21 = x12; // sin(2 * θ) again
x22 = -x11; // -cos(2 * θ)
end if
return Matrix(x11, x12, x21, x22);
/* The above line returns a matrix with the following entries:
[ x11 x12 ]
[ x21 x22 ]
*/
这是使用上述伪代码的示例伪代码:
// Reflect (x,y) over the line given by the points (a,b) and (c,d)
reflectPoint(double x, double y, double a, double b, double c, double d)
Matrix reflector = getMatrix(a, b, c, d);
Vector v1 = new Vector(x-a, x-b); // This is Step 1
Vector v2 = new Vector(a, b); // This is so we can do Step 3 later
return reflector * v1 + v2; // v1 already has Step 1 done
// reflector * v1 is Step 2
// + v2 is Step 3
有更有效的方法可以执行上述操作(例如,检查给定点之一(a,b)
和(c,d)
是否已成为原点),但上述内容仍应有效。
答案 1 :(得分:0)
修复错误之后我在这里制作了我的代码:
private Transformer2D Reflect(Vector2D p1, Vector2D p2)
{
var translationMatrix = new TranslateTransformation2D(new Vector2D(0, 0) - p1);
var inverseTranslationMatrix = new TranslateTransformation2D(p1);
var translatedP2 = translationMatrix.Transform(p2); //What p2 would be if p1 of the line was translated to the origin.
var angleWithYaxis = new Vector2D(0, 1).AngleBetweenTwoVectors(translatedP2);
var rotationMatrix = new RotationTransformation2D(-angleWithYaxis * RhinoMath.Deg2Rad);
var inverseRotationMatrix = new RotationTransformation2D(angleWithYaxis * RhinoMath.Deg2Rad);
var reflectionMatrix = new ScaleTransformation2D(-1, 1);
return new Transformer2D(translationMatrix, rotationMatrix, reflectionMatrix, inverseRotationMatrix, inverseTranslationMatrix);
}
我只使用抽象矩阵的类:
public class TranslateTransformation2D : MatrixTransformation2DBase
{
public TranslateTransformation2D(Vector2D translation)
{
TransformationMatrix = Matrix3x3.CreateTranslationMatrix(translation.X, translation.Y);
}
public TranslateTransformation2D(float x, float y)
{
TransformationMatrix = Matrix3x3.CreateTranslationMatrix(x, y);
}
}
这就是Matrix3x3类的样子:
public class Matrix3x3 : Matrix
{
public Matrix3x3(double m11, double m12, double m13,
double m21, double m22, double m23,
double m31, double m32, double m33)
{
Rows = 3;
Cols = 3;
Mat = new double[Rows * Cols];
Mat[0] = m11;
Mat[1] = m12;
Mat[2] = m13;
Mat[3] = m21;
Mat[4] = m22;
Mat[5] = m23;
Mat[6] = m31;
Mat[7] = m32;
Mat[8] = m33;
}
public static Matrix3x3 CreateTranslationMatrix(double x, double y)
{
return new Matrix3x3(1, 0, x,
0, 1, y,
0, 0, 1);
}
public static Matrix3x3 CreateScaleMatrix(double x, double y)
{
return new Matrix3x3(x, 0, 0,
0, y, 0,
0, 0, 1);
}
public static Matrix3x3 CreateIdentityMatrix()
{
return new Matrix3x3(1, 0, 0,
0, 1, 0,
0, 0, 1);
}
public static Matrix3x3 CreateRotationMatrix(double radians)
{
var cos = Math.Cos(radians);
var sin = Math.Sin(radians);
return new Matrix3x3(cos, -sin, 0,
sin, cos, 0,
0, 0, 1);
}
Transformer2D类在这里很特别,因为它只是将所有变换组合成一个矩阵,所以我们只需要应用这个矩阵来获得所有的变换:
public class Transformer2D : MatrixTransformation2DBase
{
public Transformer2D(params IMatrixTransformation2D[] transformations)
{
for (int i = transformations.Length - 1; i >= 0; i--)
{
var matrixTransformation2D = transformations[i];
if (TransformationMatrix != null)
{
TransformationMatrix = TransformationMatrix * matrixTransformation2D.TransformationMatrix;
}
else
{
TransformationMatrix = matrixTransformation2D.TransformationMatrix;
}
}
}
}
MatrixTransformation2DBase类
public abstract class MatrixTransformation2DBase : IMatrixTransformation2D
{
public Matrix3x3 TransformationMatrix { get; protected set; }
public Vector2D Transform(Vector2D vector2Din)
{
return vector2Din*TransformationMatrix;
}
}
我可能会在一些地方让它变得更快,但我的想法是我不必再担心矩阵本身,除非我想要一些新型的转换。
对于那些想知道我在内部使用什么矩阵类的人:https://github.com/darkdragon-001/LightweightMatrixCSharp
我所做的就是围绕这一点写下一些节奏。