# Triangle Button

Some code i found and adapted from somewhere. It works by basically finding the areas of the 3 triangles formed by the touch position and the corners of the triangle and comparing this with the area of the triangle

```function setup()
pt1x=100
pt1y=100
pt2x=500
pt2y=100
pt3x=500
pt3y=500
triStroke=color(255)
end

function draw()
background(40, 40, 50)

stroke(triStroke)
strokeWidth(5)
line(pt1x,pt1y,pt2x,pt2y)
line(pt2x,pt2y,pt3x,pt3y)
line(pt3x,pt3y,pt1x,pt1y)

if tpos then
stroke(255,0,0)
line(tpos.x,tpos.y,pt1x,pt1y)
line(tpos.x,tpos.y,pt2x,pt2y)
line(tpos.x,tpos.y,pt3x,pt3y)
end
end

function touched(touch)

if isPointInTriangle(touch.x,touch.y,pt1x,pt1y,pt2x,pt2y,pt3x,pt3y) then
triStroke=color(0,255,0)  else triStroke=color(255)  end
if touch.state==ENDED then tpos=nil triStroke=color(255) else
tpos=vec2(touch.x,touch.y) end
end

function triArea(p1x,p1y,p2x,p2y,p3x,p3y)
local dA = p1x - p3x
local dB = p1y - p3y
local dC = p2x - p3x
local dD = p2y - p3y
return 0.5 * math.abs((dA*dD)-(dB*dC))
end

function isPointInTriangle(px,py,p1x,p1y,p2x,p2y,p3x,p3y)
local areaT=triArea(p1x,p1y,p2x,p2y,p3x,p3y)
local areaA=triArea(px,py,p1x,p1y,p2x,p2y)
local areaB=triArea(px,py,p3x,p3y,p2x,p2y)
local areaC=triArea(px,py,p1x,p1y,p3x,p3y)
return (areaT==(areaA+areaB+areaC))
end

``````

Very cool

Had to tweak it a little bit to make it work though

I don’t know if it’s any more or less efficient but here’s my version

``````Triangle = class()

function Triangle:init(p1,p2,p3,loc,strokew)
self.p = {}
self.p[1],self.p[2],self.p[3]=p1 or vec2(0,0),p2 or vec2(100,0),p3 or vec2(50,87)
self.cent = vec2((1/3)*(self.p[1].x+self.p[2].x+self.p[3].x),(1/3)*(self.p[1].y+self.p[2].y+self.p[3].y))
for i=1,3 do
self.p[i] = self.p[i]-self.cent
end
self.cent = vec2(0,0)
self.loc = loc or vec2(WIDTH/2,HEIGHT/2)
self.ang = 0
self.col = color(255)
self.q={}
self:rebuildq()
self.sw = strokew or 1
end

function Triangle:draw()
pushStyle()
stroke(self.col)
strokeWidth(self.sw)
line(self.q[1].x,self.q[1].y,self.q[2].x,self.q[2].y)
line(self.q[2].x,self.q[2].y,self.q[3].x,self.q[3].y)
line(self.q[1].x,self.q[1].y,self.q[3].x,self.q[3].y)
popStyle()
end

if ang then
self.ang = self.ang + ang
else
self.ang = ang
end
else
self.ang = 0
end
self:qrot()
end

function Triangle:qrot()
for i=1,3 do
local dist = self.p[i]-self.cent
self.q[i] = self.q[4]+dist:rotate(self.ang)
end
end

function Triangle:setcol(newcol)
self.col = newcol
end

if loc then
self.loc = self.loc + loc
else
self.loc = loc
end
end
self:rebuildq()
end

function Triangle:move(x,y)
if x and y then
self:setloc(vec2(x,y),true)
end
end

function Triangle:rebuildq()
if not self.q[5] then
self.q[5] = vec2(0,0)
for i=1,3 do
if not self.q[i] then
self.q[i] = self.p[i]
end
end
end
for i=1,3 do
end
self.q[5] = self.loc
end

function Triangle:touched(touch)
local alpha = ((self.q[2].y-self.q[3].y)*(touch.x-self.q[3].x)+(self.q[3].x-self.q[2].x)*(touch.y-self.q[3].y))/((self.q[2].y-self.q[3].y)*(self.q[1].x-self.q[3].x)+(self.q[3].x-self.q[2].x)*(self.q[1].y-self.q[3].y))
local beta = ((self.q[3].y - self.q[1].y)*(touch.x - self.q[3].x) + (self.q[1].x - self.q[3].x)*(touch.y - self.q[3].y)) /((self.q[2].y - self.q[3].y)*(self.q[1].x - self.q[3].x) + (self.q[3].x - self.q[2].x)*(self.q[1].y - self.q[3].y))
local gamma = 1.0 - alpha - beta
return (alpha > 0 and beta > 0 and gamma > 0)
end
``````

EDITEDIT: I replied early in the morning and seem to have forgotten to be polite. Great job, App_maker! triangles are very difficult to work with

Not sure how it work but it looks good

Nice. I can share this version if anyone needs touch code for 3d triangle. Returns distance to triangle or false.

``````-- http://en.wikipedia.org/wiki/MÃ¶ller–Trumbore_intersection_algorithm
function trintersect(origin, dir, v1, v2, v3)
local epsilon = .001
local e1, e2 = v2-v1, v3-v1
local pv = dir:cross(e2)
local det = e1:dot(pv)
if det > -epsilon and det < epsilon then return false end
local invDet = 1/det
local tv = origin - v1
local u = tv:dot(pv) * invDet
if (u < 0) or (u > 1) then return false end
local qv = tv:cross(e1)
local v = dir:dot(qv) * invDet
if v < 0 or (u+v) > 1 then return false end
local hitDistance = e2:dot(qv) * invDet
return (hitDistance >= 0) and hitDistance or false
end
``````

Here’s a version of triangle buttons that I have.

``````
displayMode(FULLSCREEN)

function setup()
tri={}  -- table for triangles
-- setup triangle points and color
table.insert(tri,triangle(vec2(200,300),vec2(400,300),
vec2(300,500),color(0,255,0)))
table.insert(tri,triangle(vec2(600,200),vec2(700,300),
vec2(600,400),color(0,0,255)))
table.insert(tri,triangle(vec2(400,500),vec2(500,500),
vec2(600,700),color(255,0,255)))
table.insert(tri,triangle(vec2(100,500),vec2(200,500),
vec2(200,700),color(200,40,100)))
table.insert(tri,triangle(vec2(500,50),vec2(700,50),
vec2(300,200),color(100,200,200)))
table.insert(tri,triangle(vec2(600,600),vec2(750,600),
vec2(650,500),color(200,100,100)))
end

function draw()
background(40, 40, 50)
fill(255)
text("Touch a triangle",WIDTH/2,HEIGHT-50)
for a,b in pairs(tri) do    -- draw triangles
b:draw()
end
end

function touched(t)
for a,b in pairs(tri) do    -- check if triangle was touched
b:touched(t)
end
end

triangle = class()

function triangle:init(p1,p2,p3,col)    -- 3 points and color
self.col=col
self.tx=0
self.ty=0
self.pressed=false
self.m=mesh()
self.m.vertices={p1,p2,p3}
self.m:setColors(self.col)
end

function triangle:draw()
self.m:draw()
self:check()
if self.pressed then
self.m:setColors(255,0,0)   -- set touched color to red
fill(255,0,0)
text("PRESSED",WIDTH/2,HEIGHT-80)
else
self.m:setColors(self.col)  -- set color to original color
end
end

function triangle:touched(t)    -- get touch point
if t.state==BEGAN or t.state==MOVING then
self.tx=t.x
self.ty=t.y
else
self.tx=0
self.ty=0
self.pressed=false
end
end

function triangle:check()   -- check if touched inside of triangle
local s,a1,a2,b1,b2,b3
s=#self.m.vertices
self.pressed=false
for z=1,s do
a1,a2=false,false
if self.m.vertices[z].y>self.ty then
a1=true
end
if self.m.vertices[s].y>self.ty then
a2=true
end
b1=self.m.vertices[s].x-self.m.vertices[z].x
b2=self.ty-self.m.vertices[z].y
b3=self.m.vertices[s].y-self.m.vertices[z].y
if a1~=a2 and self.tx<(b1*b2/b3+self.m.vertices[z].x) then
self.pressed=not self.pressed
end
s=z
end
end

``````