Share Your Code

Calculating area of an object

Posted by horacebury, Posted on January 7, 2012

I have wanted to calculate the mass of an object for use in my previously submitted sample code (trajectory plotting.) The following code does that - calculates the area of an object, where it's points are clockwise in order and do not overlap. The limitation of 8 points maximum is not present. Using files produced from PhysicsEditor (that of a table of tables to represent more than 8 points) is left as an exercise for the developer...

(Because Box2D - in Corona - does not return the mass of a physics body, it is difficult to plot the trajectory of the object based on the force you apply to it because you won't be able to calculate the initial velocity. Knowing the area of the object and the fact that Box2D multiplies the area by the density to find the mass allows you to find the initial velocity after applying the force and thus the trajectory path - before it travels through it.)

The function to calculate the area is the 'calcArea' function - the others are for support of the rendering process.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
-- Does the work of calculating the area of an object made of multiple points
function calcArea( points )
        local area, perimeter = 0, 0
        
        -- check that the last point is in the same location as the first (to get the perimeter right)
        if (points[1].x ~= points[#points].x or points[1].y ~= points[#points].y) then
                points[ #points+1 ] = { x=points[1].x, y=points[1].y }
        end
        
        for i=2, #points do
                local xminus = (points[i].x - points[i-1].x)
                local yminus = (points[i].y - points[i-1].y)
                local yplus = (points[i].y + points[i-1].y)
                local xplusy = xminus*xminus + yminus*yminus
                
                area = area + ( xminus * yplus / 2 )
                perimeter = perimeter + math.sqrt( xplusy*xplusy )
        end
        
        return area, perimeter
end
 
-- Draws an object on screen from a table of point objects
function drawPoints( points )
        local group = display.newGroup()
        group.xScale, group.yScale = 1, -1
        group.x, group.y = 100, 400
        local mult = 50
        print( points[1].x, points[1].y )
        for i=2, #points do
                local line = display.newLine( group, points[i-1].x*mult, points[i-1].y*mult, points[i].x*mult, points[i].y*mult )
                line.width = 4
                print( points[i].x, points[i].y )
        end
        local line = display.newLine( group, points[1].x*mult, points[1].y*mult, points[#points].x*mult, points[#points].y*mult )
        line.width = 4
end
 
-- Converts a Corona object definition (simple table of nothing more than x and y values)
-- into a table of object containing x and y properties
-- This means the table output from this function has half the indices of the input table
-- This function also renders to the console the output table for easy copy-paste into your code
function listToPoints( list )
        local points = {}
        
        print('local points = {')
        for i=1, #list-1, 2 do
                points[ #points+1 ] = { x=list[i], y=list[i+1] }
                print('    { x='..points[#points].x..', y='..points[#points].y..' },' )
        end
        print('}')
        
        print('points: '..#points)
        return points
end
 
-- Complex shape
local list = { 1,0,0,1,.5,1.8,1,2,3,2.3,4,2.5,4.5,3,5,3.5,5.8,4,6,4,6.3,3.8,6.5,5,7,6.5,7.5,7,8,6,8,5,7,3,4,1.5,2,0.8,1,0 }
 
-- Square, to check the calcArea function actually works
--local list = { 0,0 , 0,10 , 10,10 , 10,0 }
 
local area, perim = calcArea( listToPoints( list ) )
drawPoints( listToPoints( list ) )
print('area: '..area,'perimeter: '..perim)