# Advanced touch detection [SOLVED]

I have a sample code like this

``````function draw()
translate(300,300)
rotate(30)
scale(2,1.5)

fill(255, 255, 255, 255)
rect(0,0,100,100)
end
``````

Which draws a tilted rectangle somewhere on the screen. I wonder how can I detect if a given point (e.g. touch) is inside the rectangle? Any thoughts are appreciated.

SOLUTION

Thanks to @Ignatz and @LoopSpace I ended up with pretty simple and elegant solution for 2D rects. Just few lines of code allow to convert a point from world coordinates to current matrix and vice verse. The full code is below.

``````mm = matrix()

function draw()
translate(300,300)
rotate(30)
scale(2,1.5)

fill(255, 255, 255, 255)
rect(0,0,100,100)

mm = modelMatrix()
end

function touched(touch)
if touch.state ~= BEGAN then return end

local localPoint = worldToLocal(touch)
local worldPoint = localToWorld(localPoint)

print(touch.x, touch.y) -- the original touch point
print(localPoint)       -- the point in rect coordinates
print(worldPoint)       -- this should be the same as the original touch

if localPoint.x >= 0 and localPoint.x <= 100 and
localPoint.y >= 0 and localPoint.y <= 100 then
print("HIT!")
end
end

function multiplyVec2ByMatrix(vec, mat)
vec = vec4(vec.x, vec.y, 0, 1)
-- Normaly the code below should look like "local resultVec = mat*vec"
-- but as soon as something is broken in Codea right now multiply them manualy
local resultVec = vec4(
mat*vec + mat*vec + mat*vec + mat*vec,
mat*vec + mat*vec + mat*vec + mat*vec,
mat*vec + mat*vec + mat*vec + mat*vec,
mat*vec + mat*vec + mat*vec + mat*vec
)
return vec2(resultVec.x, resultVec.y)
end

function localToWorld(localPoint)
return multiplyVec2ByMatrix(localPoint, mm)
end

function worldToLocal(worldPoint)
if mm:determinant() == 0 then
return nil
else
local resultVec = multiplyVec2ByMatrix(worldPoint, mm:inverse())
return vec2(resultVec.x, resultVec.y)
end
end
``````

@Iavmax Are all of your rectangles going to be drawn with translate and rotate.

Many of them. Mostly sprites. Rectangle is just an example.
Trying to figure out how this locating from coolcodea works.
Meanwhile what is the difference between modelMatrix(), viewMatrix() and projectionMatrix()?

@Iavmax If your going to be drawing sprites, then maybe you could use circles or overlapping circles or ellipses instead of rectangles. It’s very easy to determine if a touch is within a circle or ellipse.

@Ignatz This code works like a charm. Thank you! And I actually have no idea how exactly it works, so it’s a real magic That code is thanks to @LoopSpace.

I explain modelMatrix here.

https://coolcodea.wordpress.com/2014/11/26/184-what-is-modelmatrix/

Someone else had a go at explaining the other matrices

http://codea.io/talk/discussion/2909/clarity-on-identitymatrix-modelmatrix-viewmatrix-projectionmatrix

But wait until you try 3D before trying too hard to understand them.

This is where I usually link to my explanation of the matrices, but I’m told that it’s a bit too mathematical for general use!

@LoopSpace Well, if you have it already explained somewhere, please link, I would try to read for self education even if it’s too math.

BTW. I get how to convert a world point (touch) to my rect or sprite coordinates. But is it possible somehow to use this code for the opposite conversion? I mean if I have a point inside a rect how do I get a wold point?

@lavmax - in 2D, if you have a vec2 point p, then

``````p2 = modelMatrix() * p
``````

gives you the world point

@Ignatz except that mat4 \* vec4 is broken in Codea right now:

``````    print(matrix()*vec4(1,0,0,0))
print(matrix()*vec4(0,1,0,0))
print(matrix()*vec4(0,0,1,0))
print(matrix()*vec4(0,0,0,1))
``````

@lavmax http://loopspace.mathforge.org/HowDidIDoThat/Codea/Matrices/ but don’t say I didn’t warn you.

@Ignatz thank you, this really works. And mat4 * vec4 is really broken in Codea. But thanks to @LoopSpace I have function applymatrix4(v,m) which works So if

``````worldPoint = localPoint * modelMatrix()
``````

then I can assume that getting local point should be as simple as

``````localPoint = worldPoint / modelMatrix()
``````

But how to divide vec4 / mat4? Or it’s too naive and I can’t really do like this?j

PS. It’s all about 2D

Nope, it doesn’t work like that, you would need to invert modelMatrix

But you should be able to use the code I gave you above for a 3D plane, just make z=0.

@Ignatz and @LoopSpace - thank you guys for your help. I finally figured it out. The solution is in the original question above to make it easier to find if somebody will need it.

I’m sorry to make this old post up, but I had to say thank you because it helped me a lot

Thank you @lavmax , @Ignatz and @LoopSpace !