【问题标题】:Vector Math with System.Numerics带有 System.Numerics 的向量数学
【发布时间】:2016-06-15 15:26:26
【问题描述】:

我有以下代码旋转向量并始终将结果保持在正 x,y,z 平面中。 我想重构代码以使用 System.Numerics 类型 Vector3 和 Matrix4x4。 谁能帮我翻译一下。

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim rotation As Vector = New Vector(45, 0, -90)
        Dim delta As Vector = New Vector(10, 10, 10)
        Dim result As Vector = InverseVector(delta, rotation)
    End Sub

    Private Function InverseVector(ByVal _delta As Vector, ByVal _rotation As Vector) As Vector
        Dim vChange As New Vector(0, 0, 0)
        Dim matX(2, 2) As Single
        Dim matY(2, 2) As Single
        Dim matZ(2, 2) As Single
        Dim negativeFactor As Int32 = 1
        Dim dDeterminate As Single
        Dim matAdjoin(2, 2) As Single
        Dim matTranspose(2, 2) As Single
        Dim matInverse(2, 2) As Single

        If _delta.X < 0 Or _delta.Y < 0 Or _delta.Z < 0 Then
            negativeFactor = -1
        End If

        Dim dRadians As Single

        dRadians = 0.0174532D * _rotation.X

        'Load the X Matrix
        matX(0, 0) = 1
        matX(0, 1) = 0
        matX(0, 2) = 0
        matX(1, 0) = 0
        matX(1, 1) = CDec(Math.Round(Math.Cos(dRadians), 4))
        matX(1, 2) = CDec(Math.Round(Math.Sin(dRadians), 4) * -1)
        matX(2, 0) = 0
        matX(2, 1) = CDec(Math.Round(Math.Sin(dRadians), 4))
        matX(2, 2) = CDec(Math.Round(Math.Cos(dRadians), 4))

        'Load up the Y Matrix
        dRadians = 0.0174532D * _rotation.Y
        matY(0, 0) = CDec(Math.Round(Math.Cos(dRadians), 4))
        matY(0, 1) = 0
        matY(0, 2) = CDec(Math.Round(Math.Sin(dRadians), 4))
        matY(1, 0) = 0
        matY(1, 1) = 1
        matY(1, 2) = 0
        matY(2, 0) = CDec(Math.Round(Math.Sin(dRadians), 4) * -1)
        matY(2, 1) = 0
        matY(2, 2) = CDec(Math.Round(Math.Cos(dRadians), 4))

        'Load up the Z Matrix
        dRadians = 0.0174532D * _rotation.Z
        matZ(0, 0) = CDec(Math.Round(Math.Cos(dRadians), 4))
        matZ(0, 1) = CDec(Math.Round(Math.Sin(dRadians), 4) * -1)
        matZ(0, 2) = 0
        matZ(1, 0) = CDec(Math.Round(Math.Sin(dRadians), 4))
        matZ(1, 1) = CDec(Math.Round(Math.Cos(dRadians), 4))
        matZ(1, 2) = 0
        matZ(2, 0) = 0
        matZ(2, 1) = 0
        matZ(2, 2) = 1

        'multiply the two matrices
        Dim resultMatrix1(2, 2) As Single
        For i As Integer = 0 To 2
            For j As Integer = 0 To 2
                resultMatrix1(i, j) = matX(i, 0) * matY(0, j) +
                                       matX(i, 1) * matY(1, j) +
                                       matX(i, 2) * matY(2, j)
            Next
        Next

        'Now mutiply ResultMatrix with X matrix
        Dim resultMatrix2(2, 2) As Single
        For i As Integer = 0 To 2
            For j As Integer = 0 To 2
                resultMatrix2(i, j) = matZ(i, 0) * resultMatrix1(0, j) +
                                       matZ(i, 1) * resultMatrix1(1, j) +
                                       matZ(i, 2) * resultMatrix1(2, j)
            Next
        Next

        'Get determinate
        dDeterminate = (resultMatrix2(0, 0) * resultMatrix2(1, 1) * resultMatrix2(2, 2)) +
                       (resultMatrix2(0, 1) * resultMatrix2(1, 2) * resultMatrix2(2, 0)) +
                       (resultMatrix2(0, 2) * resultMatrix2(2, 1) * resultMatrix2(1, 0)) -
                       (resultMatrix2(0, 2) * resultMatrix2(1, 1) * resultMatrix2(2, 0)) -
                       (resultMatrix2(0, 1) * resultMatrix2(1, 0) * resultMatrix2(2, 2)) -
                       (resultMatrix2(0, 0) * resultMatrix2(1, 2) * resultMatrix2(2, 1))

        matAdjoin(0, 0) =
            ((resultMatrix2(1, 1) * resultMatrix2(2, 2)) - (resultMatrix2(1, 2) * resultMatrix2(2, 1))) * 1
        matAdjoin(0, 1) =
            ((resultMatrix2(1, 0) * resultMatrix2(2, 2)) - (resultMatrix2(1, 2) * resultMatrix2(2, 0))) * -1
        matAdjoin(0, 2) =
            ((resultMatrix2(1, 0) * resultMatrix2(2, 1)) - (resultMatrix2(1, 1) * resultMatrix2(2, 0))) * 1
        matAdjoin(1, 0) =
            ((resultMatrix2(0, 1) * resultMatrix2(2, 2)) - (resultMatrix2(0, 2) * resultMatrix2(2, 1))) * -1
        matAdjoin(1, 1) =
            ((resultMatrix2(0, 0) * resultMatrix2(2, 2)) - (resultMatrix2(0, 2) * resultMatrix2(2, 0))) * 1
        matAdjoin(1, 2) =
            ((resultMatrix2(0, 0) * resultMatrix2(2, 1)) - (resultMatrix2(0, 1) * resultMatrix2(2, 0))) * -1
        matAdjoin(2, 0) =
            ((resultMatrix2(0, 1) * resultMatrix2(1, 2)) - (resultMatrix2(0, 2) * resultMatrix2(1, 1))) * 1
        matAdjoin(2, 1) =
            ((resultMatrix2(0, 0) * resultMatrix2(1, 2)) - (resultMatrix2(0, 2) * resultMatrix2(1, 0))) * -1
        matAdjoin(2, 2) =
            ((resultMatrix2(0, 0) * resultMatrix2(1, 1)) - (resultMatrix2(0, 1) * resultMatrix2(1, 0))) * 1

        matTranspose(0, 0) = matAdjoin(0, 0)
        matTranspose(0, 1) = matAdjoin(1, 0)
        matTranspose(0, 2) = matAdjoin(2, 0)
        matTranspose(1, 0) = matAdjoin(0, 1)
        matTranspose(1, 1) = matAdjoin(1, 1)
        matTranspose(1, 2) = matAdjoin(2, 1)
        matTranspose(2, 0) = matAdjoin(0, 2)
        matTranspose(2, 1) = matAdjoin(1, 2)
        matTranspose(2, 2) = matAdjoin(2, 2)

        matInverse(0, 0) = matTranspose(0, 0) / dDeterminate
        matInverse(0, 1) = matTranspose(0, 1) / dDeterminate
        matInverse(0, 2) = matTranspose(0, 2) / dDeterminate
        matInverse(1, 0) = matTranspose(1, 0) / dDeterminate
        matInverse(1, 1) = matTranspose(1, 1) / dDeterminate
        matInverse(1, 2) = matTranspose(1, 2) / dDeterminate
        matInverse(2, 0) = matTranspose(2, 0) / dDeterminate
        matInverse(2, 1) = matTranspose(2, 1) / dDeterminate
        matInverse(2, 2) = matTranspose(2, 2) / dDeterminate

        vChange.X =
            (Math.Abs(_delta.X * matInverse(0, 0)) +
             Math.Abs(_delta.Y * matInverse(0, 1)) +
             Math.Abs(_delta.Z * matInverse(0, 2))) * negativeFactor
        vChange.Y =
            (Math.Abs(_delta.X * matInverse(1, 0)) +
             Math.Abs(_delta.Y * matInverse(1, 1)) +
             Math.Abs(_delta.Z * matInverse(1, 2))) * negativeFactor
        vChange.Z =
            (Math.Abs(_delta.X * matInverse(2, 0)) +
             Math.Abs(_delta.Y * matInverse(2, 1)) +
             Math.Abs(_delta.Z * matInverse(2, 2))) * negativeFactor

        Return vChange
    End Function
End Class

Public Class Vector
    Public Property X() As Single
    Public Property Y() As Single
    Public Property Z() As Single
    Public Sub New(ByVal _x As Single, ByVal _y As Single, ByVal _z As Single)
        X = _x
        Y = _y
        Z = _z
    End Sub
End Class

到目前为止,我已经设法重新考虑了这一点,但我被困在 matAdjoin 上

Private Function InverseVector(ByVal _delta As Vector3, ByVal _rotation As Vector3) As Vector3
    Dim vChange As New Vector3(0, 0, 0)
    Dim matX As Matrix4x4 = Matrix4x4.Identity
    Dim matY As Matrix4x4 = Matrix4x4.Identity
    Dim matZ As Matrix4x4 = Matrix4x4.Identity
    Dim negativeFactor As Int32 = 1
    Dim determinate As Single
    Dim matAdjoin As Matrix4x4
    Dim matTranspose As Matrix4x4
    Dim matInverse As Matrix4x4
    If _delta.X < 0 Or _delta.Y < 0 Or _delta.Z < 0 Then
        negativeFactor = -1
    End If
    'Load the X Matrix
    Dim sRadians As Single = 0.0174532D * _rotation.X
    matX = Matrix4x4.CreateRotationX(sRadians)
    matX.M23 *= -1
    matX.M32 *= -1
    'Load up the Y Matrix
    sRadians = 0.0174532D * _rotation.Y
    matY = Matrix4x4.CreateRotationY(sRadians)
    'Load up the Z Matrix
    sRadians = 0.0174532D * _rotation.Z
    matZ = Matrix4x4.CreateRotationZ(sRadians)
    matZ.M12 *= -1
    matZ.M21 *= -1
    'multiply the two matrices
    Dim resultMatrix1 As Matrix4x4 = Matrix4x4.Multiply(matX, matY)
    'Now mutiply ResultMatrix with X matrix
    Dim resultMatrix2 As Matrix4x4 = Matrix4x4.Multiply(matZ, resultMatrix1)
    'Get determinate
    determinate = resultMatrix2.GetDeterminant
    'stuck on from here on
    Return vChange
End Function

【问题讨论】:

  • 这个问题是题外话,因为它不是关于特定的编程问题,而是提出了一个任务供我们完成。如果您想获得有关重构工作代码的帮助,您可以访问codereview.stackexchange.com,但请注意,他们可能也不乐意被要求为您完成所有工作。
  • 那么代码中执行matAdjoin的System.Numerics方法是什么?
  • 那么代码似乎正在构建 -x、-y 和 -z 旋转矩阵。然后计算辅因子和佐剂。查看 System.Numerics.Matrix4x4 的源代码,它会出现 Matrix4x4.Invert 可能是正确的调用。

标签: c# vb.net math vector-graphics system.numerics


【解决方案1】:

这似乎是一个解决方案。虽然我对在方法的最后 4 行中将 x,y,z 与行相乘感到不满意。

Private Function InverseVector(ByVal _delta As Vector3, ByVal _rotation As Vector3) As Vector3
    Dim vChange As New Vector3(0, 0, 0)
    Dim negativeFactor As Int32 = 1
    Dim matAdjugate As Matrix4x4
    If _delta.X < 0 Or _delta.Y < 0 Or _delta.Z < 0 Then
        negativeFactor = -1
    End If
    Dim angle As Vector3 = _rotation * 0.0174532D
    'Load the -X Matrix
    Dim negativeRotationX As Matrix4x4 = Matrix4x4.CreateRotationX(angle.X)
    negativeRotationX.M23 *= -1
    negativeRotationX.M32 *= -1
    'Load up the -Y Matrix
    Dim negativeRotationY As Matrix4x4 = Matrix4x4.CreateRotationY(angle.Y)
    negativeRotationY.M21 *= -1
    'Load up the -Z Matrix
    Dim negativeRotationZ As Matrix4x4 = Matrix4x4.CreateRotationZ(angle.Z)
    negativeRotationZ.M12 *= -1
    negativeRotationZ.M21 *= -1
    'multiply the x,y matrices
    Dim resultMatrix1 As Matrix4x4 = Matrix4x4.Multiply(negativeRotationX, negativeRotationY)
    'Now mutiply z with x,y matrix
    Dim resultMatrix2 As Matrix4x4 = Matrix4x4.Multiply(negativeRotationZ, resultMatrix1)
    Dim can As Boolean = Matrix4x4.Invert(resultMatrix2, matAdjugate)
    vChange.X = (Math.Abs(_delta.X * matAdjugate.M11) + Math.Abs(_delta.Y * matAdjugate.M12) + Math.Abs(_delta.Z * matAdjugate.M13)) * negativeFactor
    vChange.Y = (Math.Abs(_delta.X * matAdjugate.M21) + Math.Abs(_delta.Y * matAdjugate.M22) + Math.Abs(_delta.Z * matAdjugate.M23)) * negativeFactor
    vChange.Z = (Math.Abs(_delta.X * matAdjugate.M31) + Math.Abs(_delta.Y * matAdjugate.M32) + Math.Abs(_delta.Z * matAdjugate.M33)) * negativeFactor
    Return vChange
End Function

【讨论】:

    【解决方案2】:

    这也有效。

    Private Function InverseVector(ByVal _delta As Vector3, ByVal _rotation As Vector3) As Vector3
        Dim vChange As New Vector3(0, 0, 0)
        Dim negativeFactor As Int32 = 1
        Dim matAdjugate As Matrix4x4
        If _delta.X < 0 Or _delta.Y < 0 Or _delta.Z < 0 Then
            negativeFactor = -1
        End If
        Dim angle As Vector3 = _rotation * 0.0174532D
        Dim negativeRotationX As Matrix4x4 = Matrix4x4.Negate(Matrix4x4.CreateRotationX(angle.X))
        Dim negativeRotationY As Matrix4x4 = Matrix4x4.Negate(Matrix4x4.CreateRotationY(angle.Y))
        Dim negativeRotationZ As Matrix4x4 = Matrix4x4.Negate(Matrix4x4.CreateRotationZ(angle.Z))
        'multiply the x,y matrices
        Dim resultMatrix1 As Matrix4x4 = Matrix4x4.Multiply(negativeRotationX, negativeRotationY)
        'Now mutiply z with x,y matrix
        Dim resultMatrix2 As Matrix4x4 = Matrix4x4.Multiply(negativeRotationZ, resultMatrix1)
        Dim can As Boolean = Matrix4x4.Invert(resultMatrix2, matAdjugate)
        vChange.X = (Math.Abs(_delta.X * matAdjugate.M11) + Math.Abs(_delta.Y * matAdjugate.M12) + Math.Abs(_delta.Z * matAdjugate.M13)) * negativeFactor
        vChange.Y = (Math.Abs(_delta.X * matAdjugate.M21) + Math.Abs(_delta.Y * matAdjugate.M22) + Math.Abs(_delta.Z * matAdjugate.M23)) * negativeFactor
        vChange.Z = (Math.Abs(_delta.X * matAdjugate.M31) + Math.Abs(_delta.Y * matAdjugate.M32) + Math.Abs(_delta.Z * matAdjugate.M33)) * negativeFactor
        Return vChange
    End Function**strong text**
    

    【讨论】:

      猜你喜欢
      • 2012-01-05
      • 1970-01-01
      • 2012-04-26
      • 2018-02-02
      • 1970-01-01
      • 1970-01-01
      • 2016-03-14
      • 1970-01-01
      相关资源
      最近更新 更多