C# 使用矩阵在反射面上反射二维点

C# 使用矩阵在反射面上反射二维点,c#,matrix,C#,Matrix,给定任意反射线,如何用矩阵反射一组点?我尝试了以下方法,但无法使其工作: 转换系统,使系统的P1处于 起源 旋转系统,使系统与Y轴平行 轴心 执行Y轴反射 撤消旋转 撤消翻译 我正试图用C写一个方法来实现这一点,基本上我给它直线的2个点,然后我得到矩阵。此后不需要旋转。让(a,b)和(c,d)成为反射线上的任意两个点。假设您要反映的点是(x,y) 平移坐标,使(a,b)成为原点。然后(x,y)变成(x-a,y-b)。这一步只是矢量减法 反思。这就是你需要矩阵的地方。将矩阵乘以步骤1中的转换向量。

给定任意反射线,如何用矩阵反射一组点?我尝试了以下方法,但无法使其工作:

  • 转换系统,使系统的P1处于 起源

  • 旋转系统,使系统与Y轴平行
    轴心

  • 执行Y轴反射

  • 撤消旋转

  • 撤消翻译

  • 我正试图用C写一个方法来实现这一点,基本上我给它直线的2个点,然后我得到矩阵。

    此后不需要旋转。让
    (a,b)
    (c,d)
    成为反射线上的任意两个点。假设您要反映的点是
    (x,y)

  • 平移坐标,使
    (a,b)
    成为原点。然后
    (x,y)
    变成
    (x-a,y-b)
    。这一步只是矢量减法
  • 反思。这就是你需要矩阵的地方。将矩阵乘以步骤1中的转换向量。您的结果将是另一个向量(2×1矩阵)
  • 将坐标转换回原始系统。这是第1步的倒数,也就是说,这是向量加法,它只是从第1步撤消向量减法。在这一步中,您只需将
    (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) 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)
    中的一个是否已经是原点),但上述操作仍应有效。

    此后无需旋转。让
    (a,b)
    (c,d)
    成为反射线上的任意两个点。假设您要反映的点是
    (x,y)

  • 平移坐标,使
    (a,b)
    成为原点。然后
    (x,y)
    变成
    (x-a,y-b)
    。这一步只是矢量减法
  • 反思。这就是你需要矩阵的地方。将矩阵乘以步骤1中的转换向量。您的结果将是另一个向量(2×1矩阵)
  • 将坐标转换回原始系统。这是第1步的倒数,也就是说,这是向量加法,它只是从第1步撤消向量减法。在这一步中,您只需将
    (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) 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)
    中的一个是否已经是源代码),但上述方法仍应有效。

    在修复了我的输入错误后,我的代码如下所示:

    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 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);
    
        }
    
    这些类仅使用抽象矩阵:

    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类的外观:

    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 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;
        }
    }
    
    我可能会在一些地方使它更快,但我的想法是,我不必再担心矩阵本身,除非我想要一些新类型的转换

    对于那些想知道我在内部使用什么矩阵类的人来说,这是一个:


    我所做的只是围绕这一点写了一些简洁的东西。

    在修复了我在这里的输入错误后,我的代码是这样的:

    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 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);
    
        }
    
    这些类仅使用抽象矩阵:

    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类的外观:

    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 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;
        }
    }
    
    我可能会在一些地方使它更快,但我的想法是,我不必再担心矩阵本身,除非我想要一些新类型的转换

    对于那些想知道我在内部使用什么矩阵类的人来说,这是一个:


    我所做的只是围绕这一点写了一些简单的说明。

    我写下的步骤似乎很好,但我做到了