#159 Fix unproject for rotated matrix
This commit is contained in:
parent
20b05d9ec2
commit
cabaee680e
12
geometry.go
12
geometry.go
|
@ -401,13 +401,11 @@ func (m Matrix) Project(u Vec) Vec {
|
|||
|
||||
// Unproject does the inverse operation to Project.
|
||||
//
|
||||
// It turns out that multiplying a vector by the inverse matrix of m can be nearly-accomplished by
|
||||
// subtracting the translate part of the matrix and multplying by the inverse of the top-left 2x2
|
||||
// matrix, and the inverse of a 2x2 matrix is simple enough to just be inlined in the computation.
|
||||
//
|
||||
// Time complexity is O(1).
|
||||
func (m Matrix) Unproject(u Vec) Vec {
|
||||
d := (m[0] * m[3]) - (m[1] * m[2])
|
||||
u.X, u.Y = (u.X-m[4])/d, (u.Y-m[5])/d
|
||||
return Vec{u.X*m[3] - u.Y*m[1], u.Y*m[0] - u.X*m[2]}
|
||||
det := m[0]*m[3] - m[2]*m[1]
|
||||
return Vec{
|
||||
m[3]/det*u.X - m[2]/det*u.Y + m[2]*m[5] - m[3]*m[4],
|
||||
-m[1]/det*u.X + m[0]/det*u.Y + m[1]*m[4] - m[0]*m[5],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package pixel_test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/faiface/pixel"
|
||||
|
@ -77,3 +79,30 @@ func TestResizeRect(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatrix_Unproject(t *testing.T) {
|
||||
t.Run("for rotated matrix", func(t *testing.T) {
|
||||
matrix := pixel.IM.Rotated(pixel.ZV, math.Pi/2)
|
||||
unprojected := matrix.Unproject(pixel.V(0, 1))
|
||||
assert.InDelta(t, unprojected.X, 1, 0.01)
|
||||
assert.InDelta(t, unprojected.Y, 0, 0.01)
|
||||
})
|
||||
t.Run("for moved matrix", func(t *testing.T) {
|
||||
matrix := pixel.IM.Moved(pixel.V(5, 5))
|
||||
unprojected := matrix.Unproject(pixel.V(0, 0))
|
||||
assert.InDelta(t, unprojected.X, -5, 0.01)
|
||||
assert.InDelta(t, unprojected.Y, -5, 0.01)
|
||||
})
|
||||
t.Run("for scaled matrix", func(t *testing.T) {
|
||||
matrix := pixel.IM.Scaled(pixel.ZV, 2)
|
||||
unprojected := matrix.Unproject(pixel.V(4, 4))
|
||||
assert.InDelta(t, unprojected.X, 2, 0.01)
|
||||
assert.InDelta(t, unprojected.Y, 2, 0.01)
|
||||
})
|
||||
t.Run("for singular matrix", func(t *testing.T) {
|
||||
matrix := pixel.Matrix{0, 0, 0, 0, 0, 0}
|
||||
unprojected := matrix.Unproject(pixel.ZV)
|
||||
assert.True(t, math.IsNaN(unprojected.X))
|
||||
assert.True(t, math.IsNaN(unprojected.Y))
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue