Triangle area and Centroid

Thought this may be a useful little thing for some, so I decided to post it here. I was just playing around when I discovered it, but I hope it helps someone. Touch a corner to resize the triangle. Touch the centroid (center) to move the entire triangle. While the centroid is being held down, you cannot resize the triangle and the corners instead serve to rotate it.

displayMode(FULLSCREEN)
function setup()
    p = {}
    q = {}
    p[1] = vec2(50,50)
    p[2] = vec2(200,50)
    p[3] = vec2(125,50+75*math.sqrt(3))
    p[4] = vec2((1/3)*(p[1].x+p[2].x+p[3].x),(1/3)*(p[1].y+p[2].y+p[3].y))
    q[1] = nil
    q[2] = nil
    q[3] = nil
    q[4] = nil
    csize = 50
    m = mesh()
    m.vertices = {p[1],p[2],p[3]}
    m:setColors(0,0,0,255)
    area = nil
    getarea()
end
function draw()
    background(255,255,255)
    fill(0,0,0,0)
    stroke(0,0,255)
    strokeWidth(1)
    ellipse(p[1].x,p[1].y,csize)
    ellipse(p[2].x,p[2].y,csize)
    ellipse(p[3].x,p[3].y,csize)
    stroke(0,0,0)
    m:draw()
    line(p[1].x,p[1].y,p[2].x,p[2].y)
    line(p[3].x,p[3].y,p[2].x,p[2].y)
    line(p[1].x,p[1].y,p[3].x,p[3].y)
    stroke(0,0,255)
    ellipse(p[4].x,p[4].y,csize)
    strokeWidth(2)
    ellipse(p[4].x,p[4].y,3)
    fill(0,0,255)
    text("Area in pixels: "..area,WIDTH/2,HEIGHT-20)
    text("Coordinates of the Centroid: "..tostring(p[4]),WIDTH/2,HEIGHT-40)
end
function touched(t)
    local used = false
    if t.state == BEGAN then
        for i=1,3 do
            if p[i]:dist(vec2(t.x,t.y)) <= csize and not used and not q[i] then
                q[i] = t.id
                used = not used
            end
        end
        if not used and p[4]:dist(vec2(t.x,t.y)) <= csize and not q[4] then
            q[4] = t.id
        end
    end
    if t.state == MOVING then
        if not q[4] then
            for i=1,3 do
                if q[i] == t.id then
                    p[i] = p[i] + vec2(t.deltaX,t.deltaY)
                    m.vertices = {p[1],p[2],p[3]}
                    p[4] = vec2((1/3)*(p[1].x+p[2].x+p[3].x),(1/3)*(p[1].y+p[2].y+p[3].y))
                end
            end
            else
            local rotating = false
            for i=1,3 do
                if q[i] == t.id and not rotating then
                    rotating = not rotating
                    local dist = p[i]:dist(p[4])
                    local ang1 = math.atan2(p[i].y-p[4].y,p[i].x-p[4].x)
                    local ang = math.atan2(t.y-p[4].y,t.x-p[4].x)
                    p[i] = vec2(0,dist):rotate(ang-(math.pi/2))+p[4]
                    local nope = i
                    local diff = ang1-ang
                    for b=1,3 do
                        if nope ~= b then
                            local dist = p[b]:dist(p[4])
                            local ang = math.atan2(p[b].y-p[4].y,p[b].x-p[4].x)
                            ang = ang - diff
                            p[b] = vec2(0,dist):rotate(ang-(math.pi/2))+p[4]
                        end
                    end
                end
            end
        end
        if q[4] == t.id then
            for i=1,4 do
                p[i] = p[i] + vec2(t.deltaX,t.deltaY)
            end
        end
        m.vertices = {p[1],p[2],p[3]}
        getarea()
    end
    if t.state == ENDED then
        for i=1,4 do
            if q[i] == t.id then
                q[i] = nil
            end
        end
    end
end
function getarea()
    local d1=p[1]:dist(p[2])
    local d2=p[2]:dist(p[3])
    local d3=p[3]:dist(p[1])
    local s=((d1+d2+d3)/2)
    area=math.sqrt(s*(s-d1)*(s-d2)*(s-d3))
    output.clear()
end