Introduction
Calculating the area (and perimeter) of polygons is an important task in nearly all branches of science and technology, including engineering, mathematics, computer science, and bioinformatics. This article provides a brief overview of the Surveyor’s formula, and presents a JavaScript implementation that allows the area of arbitrary polygons to be calculated using a form contained in a Web page. Using this JavaScript implementation, a user can easily calculate the areas of more interesting, unusual, and challenging polygons. The code also allows the polygon's perimeter to be calculated using no additional data.
Background
Many practical applications of science and technology (including engineering, mathematics, computer science, and bioinformatics) require calculating the area of regular and irregular polygons. For example, an engineer may be required to calculate the area of an unusual shape in order to determine that shape's moment of inertia, a mathematician may want the area between the x-axis and an experimentally determined curve, a computer scientist may be need the area of some program-generated graphics object, or a bioinformatician may be interested in the area of a cell displayed in a digital image.
A polygon is planar figure having three or more sides. The triangle, square, trapezoid, and parallelogram are familiar polygons. More generally, the closed shape produced by any sequence of three or more line segments connected end-to-end is also a polygon. The sides of a polygon are called edges, and the points where the edges meet are called vertices.
As a student of elementary mathematics, algebra, or geometry, you were probably taught to apply standard formulas to calculate the areas of regular polygons such as the equilateral triangle, square, pentagon, and hexagon. You also likely learned how to calculate the areas of simpler irregular polygons such as triangles, rectangles, trapezoids, and parallelograms. These kinds of problems are important because examples of both regular and irregular polygons can be found in nature. When faced with the problem of finding the area of a more complicated polygon that did not match one of these standard shapes, you were probably taught to decompose that complicated polygon into two or more simpler shapes whose areas could then be found using standard formulas.
Here is an image of an irregular polygon. How would you go about finding the area of this figure?
In order to apply the standard formulas, the lengths, widths, or heights of the simpler shapes must be found, and in all but the most trivial problems, that process ultimately requires finding the coordinates of each vertex, then using those coordinates to calculate the required distances. When this procedure is performed by hand, ample opportunities arise to unintentionally introduce computational errors and arrive at an incorrect answer.
However, if the polygon's vertex coordinates can easily be found (perhaps by reading them from a scaled figure), or if those coordinates are otherwise available, no decomposition is required, and the polygon’s area may be calculated exactly using the Surveyor’s formula.
If the polygon is described by a set of n vertices that are labeled P_{0}, P_{1}, ..., P_{n-1} and are identified in a counterclockwise manner from any initial vertex, and if each P_{k} has coordinates (x_{k},y_{k}), the Surveyor’s formula may simply be written as:
A = (x_{0}y_{1} + x_{1}y_{2} + ... + x_{n-1}y_{0} - y_{0}x_{1} - y_{1}x_{2} - ... - y_{n-1}x_{0}) / 2
If we assign P_{n} = P_{0}, and if the increments dx_{k} and dy_{k} are measured to the next vertex,
dy_{k} = y_{k+1} - y_{k}, dx_{k} = x_{k+1} - x_{k}
The Surveyor's formula can also be written as:
A = x_{0}dy_{0} - y_{0}dx_{0} + x_{1}dy_{1} - y_{1}dx_{1} + ... + x_{n-1}dy_{n-1} - y_{n-1}dx_{n-1}
To implement the Surveyor's formula in JavaScript, we will write a function to read and store the number of vertices and the x and y coordinates for each vertex, a second function to calculate and return the polygon's enclosed area, a third function to calculate and return the polygon's perimeter, and a fourth function that serves as an event handler and controls the overall process.
Implementation and Code
The following JavaScript/HTML code defines a document that contains a form allowing a user to specify a polygon's shape by entering the number of vertices and each vertex’s coordinates. The form contains a Calculate button that, when clicked, executes the JavaScript function named handleCalculate()
. That function, in turn, calls the functions readUserData()
, calculateArea()
, calculatePerimeter()
, and displayCoordinates()
to read the user’s input, parse the coordinate values, calculate the polygon’s area and perimeter, and display the results using the specified number of decimal digits. In this sample, up to 10 vertices may be entered. If more vertices are involved, additional table rows with textboxes having IDs X10, X11, ..., must be added to the form's table. The number of vertices will be read and the additional vertices will be read, stored, and processed.
For test and demonstration purposes, the form also contains a button labeled Load Vertices that, when clicked, executes the JavaScript function named loadVertices()
. That function reads the number of vertices requested, calculates the x and y coordinates for a sequence of vertices representing a polygon inscribed on a unit circle, and loads those values into the form. Increasing the number of vertices and recalculating the inscribed polygon’s area and perimeter will demonstrate generating numerical values for the inscribed polygon's area and perimeter that approach those of a unit circle.
<html>
<head>
<title>Polygon Area and Perimeter</title>
<style>
<!--
body {background-color:#FF9900;}
table {background-color:#FF9900;}
.content {width:800px; background-color:white; padding:10px;}
-->
</style>
<script language="JavaScript">
var x = new Array();
var y = new Array();
var vertices;
var digits;
var area;
var perimeter;
function readUserData()
{
vertices = parseInt( document.getElementById("VERTICES").value );
if( (vertices < 3) || (vertices > 10 ) ) {
alert( "Vertices must be >= 3 and <= 10" );
return;
}
digits = parseInt( document.getElementById("DIGITS").value );
if( digits < 0 ) {
alert( "Digits must be > 0" );
return;
}
for( k = 0; k < vertices; k++ ) {
x[k] = parseFloat( document.getElementById("X"+k).value );
y[k] = parseFloat( document.getElementById("Y"+k).value );
}
x[vertices] = x[0];
y[vertices] = y[0];
}
function calculateArea()
{
area = 0.0;
for( k = 0; k < vertices; k++ ) {
xDiff = x[k+1] - x[k];
yDiff = y[k+1] - y[k];
area = area + x[k] * yDiff - y[k] * xDiff;
}
area = 0.5 * area;
}
function calculatePerimeter()
{
perimeter = 0.0
for( k = 0; k < vertices; k++ ) {
xDiff = x[k+1] - x[k];
yDiff = y[k+1] - y[k];
perimeter = perimeter +
Math.pow( xDiff*xDiff +
yDiff*yDiff, 0.5 );
}
}
function displayCoordinates()
{
for( k = 0; k < vertices; k++ ) {
document.getElementById("X"+(k)).value =
x[k].toFixed(digits);
document.getElementById("Y"+(k)).value =
y[k].toFixed(digits);
}
}
function handleCalculate()
{
readUserData();
calculateArea();
calculatePerimeter();
displayCoordinates();
document.getElementById("AREA").value =
area.toFixed(digits);
document.getElementById("PERIMETER").value =
perimeter.toFixed(digits);
}
function loadVertices()
{
for( k = 0; k < 10; k++ ) {
document.getElementById("X"+k).value = "";
document.getElementById("Y"+k).value = "";
}
document.getElementById("AREA").value = "";
document.getElementById("PERIMETER").value = "";
vertices = parseInt( document.getElementById("VERTICES").value );
if( (vertices < 3) || (vertices > 10 ) ) {
alert( "Vertices must be >= 3 and <= 10" );
return;
}
digits = parseInt(document.getElementById("DIGITS").value );
if( digits < 0 ) {
alert( "Digits must be > 0" );
return;
}
angle = 2 * Math.PI / vertices;
for( k = 0; k < vertices; k++ ) {
xvalue = 0.5 * Math.cos( angle * k );
yvalue = 0.5 * Math.sin( angle * k );
document.getElementById("X"+k).value =
xvalue.toFixed(digits);
document.getElementById("Y"+k).value =
yvalue.toFixed(digits);
}
}
</script>
</head>
<body>
<div align="center">
<div class="content">
<form>
<table border="2" cellspacing="0"
cellpadding="2" style="border-collapse: collapse">
<tr>
<td colspan="4">
<p align="center">
<img border="0" src="Polygon.gif" width="80"
height="60" align="center"><font size="5">Polygon
Area and Perimeter Calculator</font></td>
</tr>
<tr>
<td colspan="2">Number of Vertices
<input type="text" id="VERTICES"
size="5" value="3"></td>
<td colspan="2">Displayed Decimal Digits
<input type="text" size="5" id="DIGITS"
value="3"></td>
</tr>
<tr>
<td align="center">Vertex</td>
<td colspan="2" align="left">X Value</td>
<td align="left">Y Value</td>
</tr>
<tr>
<td align="center">1</td>
<td colspan="2"><input type="text"
id="X0" size="20"></td>
<td><input type="text" id="Y0" size="20"></td>
</tr>
<tr>
<td align="center">2</td>
<td colspan="2"><input type="text"
id="X1" size="20"></td>
<td><input type="text" id="Y1" size="20"></td>
</tr>
<tr>
<td align="center">3</td>
<td colspan="2"><input type="text"
id="X2" size="20"></td>
<td><input type="text" id="Y2" size="20"></td>
</tr>
<tr>
<td align="center">4</td>
<td colspan="2"><input type="text"
id="X3" size="20"></td>
<td><input type="text" id="Y3" size="20"></td>
</tr>
<tr>
<td align="center">5</td>
<td colspan="2"><input type="text"
id="X4" size="20"></td>
<td><input type="text" id="Y4" size="20"></td>
</tr>
<tr>
<td align="center">6</td>
<td colspan="2"><input type="text"
id="X5" size="20"></td>
<td><input type="text" id="Y5" size="20"></td>
</tr>
<tr>
<td align="center">7</td>
<td colspan="2"><input type="text"
id="X6" size="20"></td>
<td><input type="text" id="Y6" size="20"></td>
</tr>
<tr>
<td align="center">8</td>
<td colspan="2"><input type="text"
id="X7" size="20"></td>
<td><input type="text" id="Y7" size="20"></td>
</tr>
<tr>
<td align="center">9</td>
<td colspan="2"><input type="text"
id="X8" size="20"></td>
<td><input type="text" id="Y8" size="20"></td>
</tr>
<tr>
<td align="center">10</td>
<td colspan="2"><input type="text"
id="X9" size="20"></td>
<td><input type="text" id="Y9" size="20"></td>
</tr>
<tr>
<td align="right">Perimeter </td>
<td colspan="2"><input type="text"
id="PERIMETER" size="20"></td>
<td> </td>
</tr>
<tr>
<td align="right">Area </td>
<td colspan="2"><input type="text"
id="AREA" size="20"></td>
<td> </td>
</tr>
<tr>
<td align="center"><input type="button"
value="Calculate" onClick="handleCalculate()"></td>
<td colspan="2" align="center">
<input type="button" value="Load Vertices"
onClick="loadVertices()"></td>
<td align="center">
<input type="reset" value="Reset"></td>
</tr>
</table>
<p align="left"><b>Instructions</b></p>
<p align="left">To calculate the area and perimeter
of an arbitrary polygon, begin by numbering
the polygon's vertices starting at 1,
proceeding in a counter-clockwise manner.
Enter the number of vertices in the form below,
then enter each vertex's x and y values. After entering
the required data, click the Calculate button
to obtain the polygon's area and perimeter.
As written, the calculator can process up to 10 vertices.</p>
<p align="left">To calculate the area
and perimeter of a regular polygon inscribed in a
circle having a radius of 1.0, enter
the number of vertices in the form below,
then click the Load Vertices button.
A set of vertex coordinates will
automatically be loaded. </p>
<p align="left">After clicking
the Calculate or Load Vertices buttons, the coordinate values,
area and perimeter will displayed using the specified number of
decimal digits. The coordinate values
displayed are those used to calculate the
area and perimeter, so changing the
displayed decimal digits may change the x
and y coordinate values and may result
in the calculation of different values
for the polygon's area and perimeter.
For many practical problems of interest, results
calculated and displayed using 3 decimal digits are adequate.</p>
<p align="left">Clicking the Reset button
will erase the form's content and set the number of
vertices and displayed decimal digits to 3.</p>
</form>
</div>
</div>
</body>
</html>
A Sample Problem
The surveyor’s formula provides an easy, efficient, and unified method for calculating the area of any polygon. It is an often-overlooked alternative technique for calculating the area of any polygon. Using the HTML document above, the area and perimeter of this polygon may easily be found.
Table 1 contains a set of sample data for an irregular polygon having 10 vertices. The polygon’s shape is shown in Figure 1. The area of this relatively simple polygon is not easily obtainable by decomposing the polygon into simpler, more familiar shapes.
Using the HTML document listed above, the area of this polygon is easily found to be 3.188 and the perimeter to be 7.772.
Table 1: Coordinates of an irregular polygon
x |
y |
1.305 |
0 |
0.567 |
0.412 |
0.458 |
1.408 |
-0.384 |
1.182 |
-0.99 |
0.72 |
-1.03 |
0 |
-1.061 |
-0.771 |
-0.229 |
-0.704 |
0.275 |
-0.848 |
0.476 |
-0.346 |
1.305 |
0 |
Figure 1: An irregular polygon
History