Touching triangle

Hey I did a forum search, but I couldn’t find anything that worked, so does anyone know how to detect if a touch is inside a triangle?

This answer seems good. You calculate some cross products and check if they are all positive or all negative. If so, the point is in the triangle.

http://math.stackexchange.com/questions/51326/determining-if-an-arbitrary-point-lies-inside-a-triangle-defined-by-three-points

Codea has a function that does cross products as required by this solution

@Ignatz, thanks!

In case anyone needs it, here’s the function i wrote to tell if a point is in a triangle:

function pointInTriangle(A, B, C, P)
    local line1 = B - A
    local tline1 = P - A
    local cross1 = tline1:cross(line1)
    local line2 = C - B
    local tline2 = P - B
    local cross2 = tline2:cross(line2)
    local line3 = A - C
    local tline3 = P - C
    local cross3 = tline3:cross(line3)
    if (cross1 < 0 and cross2 < 0 and cross3 < 0) or
    (cross1 > 0 and cross2 > 0 and cross3 > 0) then
        return true
    else
        return false
    end
end

Touch inside or outside of the triangle.


displayMode(FULLSCREEN)

function setup()
    tx=350
    ty=650
    verts1={vec2(200,300),vec2(500,300),vec2(350,600)}
end

function draw()
    background(40, 40, 50)
    stroke(255)
    strokeWidth(2)
    j=#verts1
    for z=1,#verts1 do
        line(verts1[z].x,verts1[z].y,verts1[j].x,verts1[j].y)
        j=z
    end    
    ellipse(tx,ty,10)       
    check() 
    fill(255)   
    text(str,350,700)  
end

function check()    -- check if points tx,ty are within triangle
    j=#verts1
    c=-1
    for i=1,#verts1 do
        a1=false
        if verts1[i].y>ty then
            a1=true
        end
        a2=false
        if verts1[j].y>ty then
            a2=true
        end
        b1=verts1[j].x-verts1[i].x
        b2=ty-verts1[i].y
        b3=(verts1[j].y-verts1[i].y)
        if a1~=a2 and tx<(b1*b2/b3+verts1[i].x) then
            c = c *-1
        end
        j=i
    end 
    str="outside"
    if c==1 then
        str="inside"
    end
end

function touched(t)
    tx=t.x
    ty=t.y
end

If you use the physics library you could use

function pointInTriangle(A, B, C, P)
   local b = physics.body( POLYGON, A, B, C)
   return b:testPoint(P)
end

@tnlogy - the only problem with the physics solution is that garbage collection may not destroy the triangle for a minute or so, and if you are using other physics objects, this could cause problems in the meantime.

I think a pure code solution works better here, but I must say I didn’t know about the testPoint function, that is handy.

Here’s another version using collide. Just slide your finger around the screen. I have a point and a triangle that can be moved around at the same time to overlap with the stationary triangle. I still like my first version at the top because I like math and formulas. That way I can see exactly what’s happening with the calculations.


displayMode(FULLSCREEN)

function setup()
    str=""
    c1 = physics.body(CIRCLE,1)
    p1=physics.body(POLYGON,vec2(-100,0),vec2(100,0),vec2(0,200))
    p1.type=STATIC
    p2=physics.body(POLYGON,vec2(-50,0),vec2(50,0),vec2(0,100))
end

function collide(contact)
    if contact.state == BEGAN or contact.state==MOVING then
        str="overlap"
    else
        str=""
    end
end

function draw()
    background(0, 0, 0, 255)
    stroke(255)
    strokeWidth(2)
    fill(255)
    text(str,WIDTH/2,HEIGHT/2+300)

    x=CurrentTouch.x
    y=CurrentTouch.y
    
    c1.x=0
    c1.y=0
    ellipse(x,y+250,2)
    c1.position = vec2(c1.x+x,c1.y+y+250)
    
    p1.x=WIDTH/2
    p1.y=HEIGHT/2
    a=p1.points
    j=#a
    for z=1,#a do
        line(a[z].x+p1.x,a[z].y+p1.y,a[j].x+p1.x,a[j].y+p1.y)
        j=z
    end 
    p1.position=vec2(p1.x,p1.y)

    p2.x=0
    p2.y=0
    a=p2.points
    j=#a
    for z=1,#a do
        line(a[z].x+x,a[z].y+y+100,a[j].x+x,a[j].y+y+100)
        j=z
    end  
    p2.position=vec2(p2.x+x,p2.y+y+100)
end