From cabaee680e66651f2a9a6e72996e9f21d47c274f Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Tue, 12 Feb 2019 14:57:03 +0100 Subject: [PATCH 01/11] #159 Fix unproject for rotated matrix --- geometry.go | 12 +++++------- geometry_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/geometry.go b/geometry.go index 72d148e..621a0b4 100644 --- a/geometry.go +++ b/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], + } } diff --git a/geometry_test.go b/geometry_test.go index e1c1a6f..f97b8cd 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -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)) + }) +} From 3b366d1edd6c8827556c1ff08c25d89808415fc7 Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Tue, 12 Feb 2019 15:24:17 +0100 Subject: [PATCH 02/11] #159 Use more precise delta for floats comparision --- geometry_test.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/geometry_test.go b/geometry_test.go index f97b8cd..13f90e2 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -81,23 +81,24 @@ func TestResizeRect(t *testing.T) { } func TestMatrix_Unproject(t *testing.T) { + const delta = 4e-16 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) + assert.InDelta(t, unprojected.X, 1, delta) + assert.InDelta(t, unprojected.Y, 0, delta) }) 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) + assert.InDelta(t, unprojected.X, -5, delta) + assert.InDelta(t, unprojected.Y, -5, delta) }) 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) + assert.InDelta(t, unprojected.X, 2, delta) + assert.InDelta(t, unprojected.Y, 2, delta) }) t.Run("for singular matrix", func(t *testing.T) { matrix := pixel.Matrix{0, 0, 0, 0, 0, 0} From a0713598da8ef18c7dbe0742ce8d44670cd98abb Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Tue, 12 Feb 2019 16:26:19 +0100 Subject: [PATCH 03/11] #159 Add test case for rotated and moved matrix --- geometry_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/geometry_test.go b/geometry_test.go index 13f90e2..b1ce00f 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -100,6 +100,12 @@ func TestMatrix_Unproject(t *testing.T) { assert.InDelta(t, unprojected.X, 2, delta) assert.InDelta(t, unprojected.Y, 2, delta) }) + t.Run("for rotated and moved matrix", func(t *testing.T) { + matrix := pixel.IM.Rotated(pixel.ZV, math.Pi/2).Moved(pixel.V(1, 1)) + unprojected := matrix.Unproject(pixel.V(1, 2)) + assert.InDelta(t, unprojected.X, 1, delta) + assert.InDelta(t, unprojected.Y, 0, delta) + }) t.Run("for singular matrix", func(t *testing.T) { matrix := pixel.Matrix{0, 0, 0, 0, 0, 0} unprojected := matrix.Unproject(pixel.ZV) From 1e19db5b25bbff71728a9fc283acf3775a23c4be Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Tue, 12 Feb 2019 18:40:15 +0100 Subject: [PATCH 04/11] #159 Add test case when matrix determinant is not 1 --- geometry.go | 4 ++-- geometry_test.go | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/geometry.go b/geometry.go index 621a0b4..e847b52 100644 --- a/geometry.go +++ b/geometry.go @@ -405,7 +405,7 @@ func (m Matrix) Project(u Vec) Vec { func (m Matrix) Unproject(u Vec) Vec { 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], + m[3]/det*u.X - m[2]/det*u.Y + (m[2]*m[5]-m[3]*m[4])/det, + -m[1]/det*u.X + m[0]/det*u.Y + (m[1]*m[4]-m[0]*m[5])/det, } } diff --git a/geometry_test.go b/geometry_test.go index b1ce00f..17b184f 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -100,6 +100,12 @@ func TestMatrix_Unproject(t *testing.T) { assert.InDelta(t, unprojected.X, 2, delta) assert.InDelta(t, unprojected.Y, 2, delta) }) + t.Run("for scaled, rotated and moved matrix", func(t *testing.T) { + matrix := pixel.IM.Scaled(pixel.ZV, 2).Rotated(pixel.ZV, math.Pi/2).Moved(pixel.V(2, 2)) + unprojected := matrix.Unproject(pixel.V(-2, 6)) + assert.InDelta(t, unprojected.X, 2, delta) + assert.InDelta(t, unprojected.Y, 2, delta) + }) t.Run("for rotated and moved matrix", func(t *testing.T) { matrix := pixel.IM.Rotated(pixel.ZV, math.Pi/2).Moved(pixel.V(1, 1)) unprojected := matrix.Unproject(pixel.V(1, 2)) From 0aec9fead05ecd72fb6e04bec42523e9ec187232 Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Tue, 12 Feb 2019 18:53:38 +0100 Subject: [PATCH 05/11] #159 Format code in TestMatrix_Unproject --- geometry_test.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/geometry_test.go b/geometry_test.go index 17b184f..9eb8367 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -83,31 +83,39 @@ func TestResizeRect(t *testing.T) { func TestMatrix_Unproject(t *testing.T) { const delta = 4e-16 t.Run("for rotated matrix", func(t *testing.T) { - matrix := pixel.IM.Rotated(pixel.ZV, math.Pi/2) + matrix := pixel.IM. + Rotated(pixel.ZV, math.Pi/2) unprojected := matrix.Unproject(pixel.V(0, 1)) assert.InDelta(t, unprojected.X, 1, delta) assert.InDelta(t, unprojected.Y, 0, delta) }) t.Run("for moved matrix", func(t *testing.T) { - matrix := pixel.IM.Moved(pixel.V(5, 5)) + matrix := pixel.IM. + Moved(pixel.V(5, 5)) unprojected := matrix.Unproject(pixel.V(0, 0)) assert.InDelta(t, unprojected.X, -5, delta) assert.InDelta(t, unprojected.Y, -5, delta) }) t.Run("for scaled matrix", func(t *testing.T) { - matrix := pixel.IM.Scaled(pixel.ZV, 2) + matrix := pixel.IM. + Scaled(pixel.ZV, 2) unprojected := matrix.Unproject(pixel.V(4, 4)) assert.InDelta(t, unprojected.X, 2, delta) assert.InDelta(t, unprojected.Y, 2, delta) }) t.Run("for scaled, rotated and moved matrix", func(t *testing.T) { - matrix := pixel.IM.Scaled(pixel.ZV, 2).Rotated(pixel.ZV, math.Pi/2).Moved(pixel.V(2, 2)) + matrix := pixel.IM. + Scaled(pixel.ZV, 2). + Rotated(pixel.ZV, math.Pi/2). + Moved(pixel.V(2, 2)) unprojected := matrix.Unproject(pixel.V(-2, 6)) assert.InDelta(t, unprojected.X, 2, delta) assert.InDelta(t, unprojected.Y, 2, delta) }) t.Run("for rotated and moved matrix", func(t *testing.T) { - matrix := pixel.IM.Rotated(pixel.ZV, math.Pi/2).Moved(pixel.V(1, 1)) + matrix := pixel.IM. + Rotated(pixel.ZV, math.Pi/2). + Moved(pixel.V(1, 1)) unprojected := matrix.Unproject(pixel.V(1, 2)) assert.InDelta(t, unprojected.X, 1, delta) assert.InDelta(t, unprojected.Y, 0, delta) From b0ed22e0ec1500d051d2410ce04129aa0e43c3eb Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Tue, 12 Feb 2019 21:00:05 +0100 Subject: [PATCH 06/11] #159 Simplify Matrix.Unproject formulas --- geometry.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geometry.go b/geometry.go index e847b52..03b2fea 100644 --- a/geometry.go +++ b/geometry.go @@ -405,7 +405,7 @@ func (m Matrix) Project(u Vec) Vec { func (m Matrix) Unproject(u Vec) Vec { 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])/det, - -m[1]/det*u.X + m[0]/det*u.Y + (m[1]*m[4]-m[0]*m[5])/det, + (m[3]*u.X - m[2]*u.Y + m[2]*m[5] - m[3]*m[4]) / det, + (-m[1]*u.X + m[0]*u.Y + m[1]*m[4] - m[0]*m[5]) / det, } } From 2e0da4f44a831cb7944766cc9041d2e350eb433a Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Tue, 12 Feb 2019 21:06:37 +0100 Subject: [PATCH 07/11] #159 Another reduction of Simplify Matrix.Unproject formulas --- geometry.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/geometry.go b/geometry.go index 03b2fea..4680872 100644 --- a/geometry.go +++ b/geometry.go @@ -405,7 +405,7 @@ func (m Matrix) Project(u Vec) Vec { func (m Matrix) Unproject(u Vec) Vec { det := m[0]*m[3] - m[2]*m[1] return Vec{ - (m[3]*u.X - m[2]*u.Y + m[2]*m[5] - m[3]*m[4]) / det, - (-m[1]*u.X + m[0]*u.Y + m[1]*m[4] - m[0]*m[5]) / det, + (m[3]*(u.X-m[4]) - m[2]*(u.Y-m[5])) / det, + (-m[1]*(u.X-m[4]) + m[0]*(u.Y-m[5])) / det, } } From 392fe90b11287faee831a9167e00588d1cea760a Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Wed, 13 Feb 2019 14:39:47 +0100 Subject: [PATCH 08/11] #159 Test whether Matrix.Unprejected(Matrix.Projected(vertex)) == vertex --- geometry_test.go | 49 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/geometry_test.go b/geometry_test.go index 9eb8367..8ac01c3 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -81,7 +81,7 @@ func TestResizeRect(t *testing.T) { } func TestMatrix_Unproject(t *testing.T) { - const delta = 4e-16 + const delta = 1e-15 t.Run("for rotated matrix", func(t *testing.T) { matrix := pixel.IM. Rotated(pixel.ZV, math.Pi/2) @@ -91,16 +91,16 @@ func TestMatrix_Unproject(t *testing.T) { }) 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, delta) - assert.InDelta(t, unprojected.Y, -5, delta) + Moved(pixel.V(1, 2)) + unprojected := matrix.Unproject(pixel.V(2, 5)) + assert.InDelta(t, unprojected.X, 1, delta) + assert.InDelta(t, unprojected.Y, 3, delta) }) 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, delta) + unprojected := matrix.Unproject(pixel.V(2, 4)) + assert.InDelta(t, unprojected.X, 1, delta) assert.InDelta(t, unprojected.Y, 2, delta) }) t.Run("for scaled, rotated and moved matrix", func(t *testing.T) { @@ -120,6 +120,41 @@ func TestMatrix_Unproject(t *testing.T) { assert.InDelta(t, unprojected.X, 1, delta) assert.InDelta(t, unprojected.Y, 0, delta) }) + t.Run("for projected vertices using all kinds of matrices", func(t *testing.T) { + matrices := [...]pixel.Matrix{ + pixel.IM, + pixel.IM.Scaled(pixel.ZV, 0.5), + pixel.IM.Scaled(pixel.ZV, 2), + pixel.IM.Rotated(pixel.ZV, math.Pi/4), + pixel.IM.Moved(pixel.V(0.5, 1)), + pixel.IM.Moved(pixel.V(-1, -0.5)), + pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4), + pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2)), + pixel.IM.Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2)), + } + vertices := [...]pixel.Vec{ + pixel.V(0, 0), + pixel.V(5, 0), + pixel.V(5, 10), + pixel.V(0, 10), + pixel.V(-5, 10), + pixel.V(-5, 0), + pixel.V(-5, -10), + pixel.V(0, -10), + pixel.V(5, -10), + } + for _, matrix := range matrices { + for _, vertex := range vertices { + testCase := fmt.Sprintf("for matrix %v and vertex %v", matrix, vertex) + t.Run(testCase, func(t *testing.T) { + projected := matrix.Project(vertex) + unprojected := matrix.Unproject(projected) + assert.InDelta(t, vertex.X, unprojected.X, delta) + assert.InDelta(t, vertex.Y, unprojected.Y, delta) + }) + } + } + }) t.Run("for singular matrix", func(t *testing.T) { matrix := pixel.Matrix{0, 0, 0, 0, 0, 0} unprojected := matrix.Unproject(pixel.ZV) From 0a054f35fd8d9af99cd894aec2b9df855b0cf21b Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Wed, 13 Feb 2019 15:06:50 +0100 Subject: [PATCH 09/11] #159 Name matrices in unit test to avoid confusion with test cases --- geometry_test.go | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/geometry_test.go b/geometry_test.go index 8ac01c3..b517f48 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -121,16 +121,19 @@ func TestMatrix_Unproject(t *testing.T) { assert.InDelta(t, unprojected.Y, 0, delta) }) t.Run("for projected vertices using all kinds of matrices", func(t *testing.T) { - matrices := [...]pixel.Matrix{ - pixel.IM, - pixel.IM.Scaled(pixel.ZV, 0.5), - pixel.IM.Scaled(pixel.ZV, 2), - pixel.IM.Rotated(pixel.ZV, math.Pi/4), - pixel.IM.Moved(pixel.V(0.5, 1)), - pixel.IM.Moved(pixel.V(-1, -0.5)), - pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4), - pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2)), - pixel.IM.Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2)), + namedMatrices := []struct { + name string + matrix pixel.Matrix + }{ + {"IM", pixel.IM}, + {"Scaled", pixel.IM.Scaled(pixel.ZV, 0.5)}, + {"Scaled x 2", pixel.IM.Scaled(pixel.ZV, 2)}, + {"Rotated", pixel.IM.Rotated(pixel.ZV, math.Pi/4)}, + {"Moved", pixel.IM.Moved(pixel.V(0.5, 1))}, + {"Moved 2", pixel.IM.Moved(pixel.V(-1, -0.5))}, + {"Scaled and Rotated", pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4)}, + {"Scaled, Rotated and Moved", pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2))}, + {"Rotated and Moved", pixel.IM.Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2))}, } vertices := [...]pixel.Vec{ pixel.V(0, 0), @@ -143,10 +146,11 @@ func TestMatrix_Unproject(t *testing.T) { pixel.V(0, -10), pixel.V(5, -10), } - for _, matrix := range matrices { + for _, namedMatrix := range namedMatrices { for _, vertex := range vertices { - testCase := fmt.Sprintf("for matrix %v and vertex %v", matrix, vertex) + testCase := fmt.Sprintf("for matrix %s and vertex %v", namedMatrix.name, vertex) t.Run(testCase, func(t *testing.T) { + matrix := namedMatrix.matrix projected := matrix.Project(vertex) unprojected := matrix.Unproject(projected) assert.InDelta(t, vertex.X, unprojected.X, delta) From 742d1226d8fa6008dfffbb1b6a239d697855273d Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Wed, 13 Feb 2019 15:13:04 +0100 Subject: [PATCH 10/11] #159 Make namedMatrices an array instead of slice --- geometry_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geometry_test.go b/geometry_test.go index b517f48..766f506 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -121,7 +121,7 @@ func TestMatrix_Unproject(t *testing.T) { assert.InDelta(t, unprojected.Y, 0, delta) }) t.Run("for projected vertices using all kinds of matrices", func(t *testing.T) { - namedMatrices := []struct { + namedMatrices := [...]struct { name string matrix pixel.Matrix }{ From 42cc2a0376f49fb3c6c1be02369d3b2c6d6427a5 Mon Sep 17 00:00:00 2001 From: Jacek Olszak Date: Wed, 13 Feb 2019 15:25:12 +0100 Subject: [PATCH 11/11] #159 Use map instead of array for named Matrices --- geometry_test.go | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/geometry_test.go b/geometry_test.go index 766f506..d766b1d 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -121,19 +121,16 @@ func TestMatrix_Unproject(t *testing.T) { assert.InDelta(t, unprojected.Y, 0, delta) }) t.Run("for projected vertices using all kinds of matrices", func(t *testing.T) { - namedMatrices := [...]struct { - name string - matrix pixel.Matrix - }{ - {"IM", pixel.IM}, - {"Scaled", pixel.IM.Scaled(pixel.ZV, 0.5)}, - {"Scaled x 2", pixel.IM.Scaled(pixel.ZV, 2)}, - {"Rotated", pixel.IM.Rotated(pixel.ZV, math.Pi/4)}, - {"Moved", pixel.IM.Moved(pixel.V(0.5, 1))}, - {"Moved 2", pixel.IM.Moved(pixel.V(-1, -0.5))}, - {"Scaled and Rotated", pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4)}, - {"Scaled, Rotated and Moved", pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2))}, - {"Rotated and Moved", pixel.IM.Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2))}, + namedMatrices := map[string]pixel.Matrix{ + "IM": pixel.IM, + "Scaled": pixel.IM.Scaled(pixel.ZV, 0.5), + "Scaled x 2": pixel.IM.Scaled(pixel.ZV, 2), + "Rotated": pixel.IM.Rotated(pixel.ZV, math.Pi/4), + "Moved": pixel.IM.Moved(pixel.V(0.5, 1)), + "Moved 2": pixel.IM.Moved(pixel.V(-1, -0.5)), + "Scaled and Rotated": pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4), + "Scaled, Rotated and Moved": pixel.IM.Scaled(pixel.ZV, 0.5).Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2)), + "Rotated and Moved": pixel.IM.Rotated(pixel.ZV, math.Pi/4).Moved(pixel.V(1, 2)), } vertices := [...]pixel.Vec{ pixel.V(0, 0), @@ -146,11 +143,10 @@ func TestMatrix_Unproject(t *testing.T) { pixel.V(0, -10), pixel.V(5, -10), } - for _, namedMatrix := range namedMatrices { + for matrixName, matrix := range namedMatrices { for _, vertex := range vertices { - testCase := fmt.Sprintf("for matrix %s and vertex %v", namedMatrix.name, vertex) + testCase := fmt.Sprintf("for matrix %s and vertex %v", matrixName, vertex) t.Run(testCase, func(t *testing.T) { - matrix := namedMatrix.matrix projected := matrix.Project(vertex) unprojected := matrix.Unproject(projected) assert.InDelta(t, vertex.X, unprojected.X, delta)