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
function Triangle:rotate(ang,additive)
if ang then
ang = math.rad(ang)
if additive 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
function Triangle:setloc(loc,additive)
if loc then
if additive 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
local adjust = self.loc-self.q[5]
for i=1,3 do
self.q[i] = self.q[i]+adjust
end
self.q[4] = self.cent+adjust
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
EDIT: further optimized, added rotation
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