Skip to content

Commit a10d9ae

Browse files
author
Anton Petrov
committed
affineTransform implementation
1 parent f4a492f commit a10d9ae

1 file changed

Lines changed: 153 additions & 57 deletions

File tree

playdate/affineTransform.lua

Lines changed: 153 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,66 @@ local module = {}
22
playdate.geometry.affineTransform = module
33

44
local meta = {}
5-
65
meta.__index = meta
6+
module.__index = meta
77

8-
meta.__mul = function(a, b)
9-
error("[ERR] playdate.geometry.affineTransform.__mul is not yet implemented.")
8+
local function concat(a, b)
9+
return
10+
a.m11 * b.m11 + a.m21 * b.m12,
11+
a.m12 * b.m11 + a.m22 * b.m12,
12+
a.m11 * b.m21 + a.m21 * b.m22,
13+
a.m12 * b.m21 + a.m22 * b.m22,
14+
a.tx * b.m11 + a.ty * b.m12 + b.tx,
15+
a.tx * b.m21 + a.ty * b.m22 + b.ty
1016
end
1117

12-
module.__index = meta
18+
19+
local function transform(t, x, y)
20+
return
21+
x * t.m11 + y * t.m12 + t.tx,
22+
x * t.m21 + y * t.m22 + t.ty
23+
end
24+
25+
local function translation(dx, dy)
26+
return module.new(1, 0, 0, 1, dx, dy)
27+
end
28+
29+
local function scaling(sx, sy)
30+
sy = sy or sx
31+
return module.new(sx, 0, 0, sy, 0, 0)
32+
end
33+
34+
local function rotation(angle)
35+
angle = math.rad(angle)
36+
local c = math.cos(angle)
37+
local s = math.sin(angle)
38+
return module.new(c, -s, s, c, 0, 0)
39+
end
40+
41+
local function rotationAround(angle, px, py)
42+
local rad = math.rad(angle)
43+
local c = math.cos(rad)
44+
local s = math.sin(rad)
45+
local tx = px - px * c + py * s
46+
local ty = py - px * s - py * c
47+
return module.new(c, -s, s, c, tx, ty)
48+
end
49+
50+
local function skewing(sx, sy)
51+
local rx = math.tan(math.rad(sx))
52+
local ry = math.tan(math.rad(sy))
53+
return module.new(1, rx, ry, 1, 0, 0)
54+
end
1355

1456
function module.new(m11, m12, m21, m22, tx, ty)
1557
local o = {}
1658

17-
if m11 then
18-
o.m11 = m11
19-
o.m12 = m12
20-
o.m21 = m21
21-
o.m22 = m22
22-
o.tx = tx
23-
o.ty = ty
24-
else
25-
o.m11 = 1
26-
o.m12 = 0
27-
o.m21 = 0
28-
o.m22 = 1
29-
o.tx = 0
30-
o.ty = 0
31-
end
59+
o.m11 = m11 or 1
60+
o.m12 = m12 or 0
61+
o.m21 = m21 or 0
62+
o.m22 = m22 or 1
63+
o.tx = tx or 0
64+
o.ty = ty or 0
3265

3366
setmetatable(o, meta)
3467
return o
@@ -43,7 +76,27 @@ function meta:unpack()
4376
end
4477

4578
function meta:invert()
46-
error("[ERR] playdate.geometry.affineTransform:invert() is not yet implemented.")
79+
local a, b = self.m11, self.m12
80+
local c, d = self.m21, self.m22
81+
local tx, ty = self.tx, self.ty
82+
83+
local det = a * d - b * c
84+
local invDet = 1 / det
85+
86+
local im11 = d * invDet
87+
local im12 = -b * invDet
88+
local im21 = -c * invDet
89+
local im22 = a * invDet
90+
91+
local itx = -(im11 * tx + im12 * ty)
92+
local ity = -(im21 * tx + im22 * ty)
93+
94+
self.m11 = im11
95+
self.m12 = im12
96+
self.m21 = im21
97+
self.m22 = im22
98+
self.tx = itx
99+
self.ty = ity
47100
end
48101

49102
function meta:reset()
@@ -55,88 +108,131 @@ function meta:reset()
55108
self.ty = 0
56109
end
57110

58-
function meta:concat(af)
59-
local m11 = self.m11 * af.m11 + self.m12 * af.m21
60-
local m12 = self.m11 * af.m12 + self.m12 * af.m22
61-
62-
local m21 = self.m21 * af.m11 + self.m22 * af.m21
63-
local m22 = self.m21 * af.m12 + self.m22 * af.m22
64-
65-
local tx = self.m11 * af.tx + self.m12 * af.ty + self.tx
66-
local ty = self.m21 * af.tx + self.m22 * af.ty + self.ty
67-
68-
return module.new(m11, m12, m21, m22, tx, ty)
111+
function meta:concat(b)
112+
self.m11, self.m12, self.m21, self.m22, self.tx, self.ty = concat(self, b)
69113
end
70114

71115
function meta:translate(dx, dy)
72-
error("[ERR] playdate.geometry.affineTransform:translate() is not yet implemented.")
116+
local t = translation(dx, dy)
117+
self:concat(t)
73118
end
74119

75120
function meta:translatedBy(dx, dy)
76-
error("[ERR] playdate.geometry.affineTransform:translatedBy() is not yet implemented.")
121+
local t = self:copy()
122+
t:translate(dx, dy)
123+
return t
77124
end
78125

79126
function meta:scale(sx, sy)
80-
error("[ERR] playdate.geometry.affineTransform:scale() is not yet implemented.")
127+
local t = scaling(sx, sy)
128+
self:concat(t)
81129
end
82130

83131
function meta:scaledBy(sx, sy)
84-
error("[ERR] playdate.geometry.affineTransform:scaledBy() is not yet implemented.")
132+
local t = self:copy()
133+
t:scale(sx, sy)
134+
return t
85135
end
86136

87-
function meta:rotate(angle, pointOrX, y)
88-
error("[ERR] playdate.geometry.affineTransform:rotate() is not yet implemented.")
137+
function meta:rotate(angle, x, y)
138+
local t
139+
140+
if x then
141+
if y then
142+
t = rotationAround(angle, x, y)
143+
else
144+
local pt = x
145+
t = rotationAround(angle, pt.x, pt.y)
146+
end
147+
else
148+
t = rotation(angle)
149+
end
150+
151+
self:concat(t)
89152
end
90153

91-
function meta:rotateBy(angle, pointOrX, y)
92-
error("[ERR] playdate.geometry.affineTransform:rotateBy() is not yet implemented.")
154+
function meta:rotatedBy(angle, pointOrX, y)
155+
local t = self:copy()
156+
t:rotate(angle, pointOrX, y)
157+
return t
93158
end
94159

95160
function meta:skew(sx, sy)
96-
error("[ERR] playdate.geometry.affineTransform:skew() is not yet implemented.")
161+
local t = skewing(sx, sy)
162+
self:concat(t)
97163
end
98164

99165
function meta:skewedBy(sx, sy)
100-
error("[ERR] playdate.geometry.affineTransform:skewedBy() is not yet implemented.")
166+
local t = self:copy()
167+
t:skew(sx, sy)
168+
return t
101169
end
102170

103-
function meta:transformPoint(p)
104-
local nx, ny = self:transformXY(p.x, p.y)
105-
p.x = nx
106-
p.y = ny
171+
function meta:transformXY(x, y)
172+
return transform(self, x, y)
107173
end
108174

109-
function meta:transformedPoint(p)
110-
local nx, ny = self:transformXY(p.x, p.y)
111-
return playdate.geometry.point.new(nx, ny)
175+
function meta:transformPoint(p)
176+
p.x, p.y = transform(self, p.x, p.y)
112177
end
113178

114-
function meta:transformXY(x, y)
115-
local nx = x * self.m11 + y * self.m12 + self.tx
116-
local ny = x * self.m21 + y * self.m22 + self.ty
117-
return nx, ny
179+
function meta:transformedPoint(p)
180+
local c = p:copy()
181+
self:transformPoint(c)
182+
return c
118183
end
119184

120185
function meta:transformLineSegment(ls)
121-
error("[ERR] playdate.geometry.affineTransform:transformLineSegment() is not yet implemented.")
186+
ls.x1, ls.y1 = transform(self, ls.x1, ls.y1)
187+
ls.x2, ls.y2 = transform(self, ls.x2, ls.y2)
122188
end
123189

124190
function meta:transformedLineSegment(ls)
125-
error("[ERR] playdate.geometry.affineTransform:transformedLineSegment() is not yet implemented.")
191+
local c = ls:copy()
192+
self:transformLineSegment(c)
193+
return c
126194
end
127195

128196
function meta:transformAABB(r)
129197
error("[ERR] playdate.geometry.affineTransform:transformAABB() is not yet implemented.")
130198
end
131199

132200
function meta:transformedAABB(r)
133-
error("[ERR] playdate.geometry.affineTransform:transformedAABB() is not yet implemented.")
201+
local c = r:copy()
202+
self:transformAABB(c)
203+
return c
134204
end
135205

136206
function meta:transformPolygon(p)
137-
error("[ERR] playdate.geometry.affineTransform:transformPolygon() is not yet implemented.")
207+
local pts = p._points
208+
for i = 1, #pts, 2 do
209+
local j = i + 1
210+
pts[i], pts[j] = transform(self, pts[i], pts[j])
211+
end
138212
end
139213

140214
function meta:transformedPolygon(p)
141-
error("[ERR] playdate.geometry.affineTransform:transformedPolygon() is not yet implemented.")
215+
local c = p:copy()
216+
self:transformPolygon(c)
217+
return c
142218
end
219+
220+
meta.__mul = function(a, b)
221+
if b._type == "point" then
222+
local x, y = transform(a, b.x, b.y)
223+
return playdate.geometry.point.new(x, y)
224+
225+
elseif b._type == "vector2D" then
226+
local dx, dy = transform(a, b.dx, b.dy)
227+
return playdate.geometry.vector2D.new(dx, dy)
228+
229+
else
230+
local m11, m12, m21, m22, tx, ty = concat(a, b)
231+
return module.new(m11, m12, m21, m22, tx, ty)
232+
end
233+
end
234+
235+
meta.__tostring = function(t)
236+
return string.format("(m11=%s, m12=%s, m21=%s, m22=%s, tx=%s, ty=%s)",
237+
t.m11, t.m12, t.m21, t.m22, t.tx, t.ty)
238+
end

0 commit comments

Comments
 (0)