Click here to Skip to main content
Click here to Skip to main content

Polyhedra Volume Calculations - A JavaScript Implementation

, 3 Apr 2006
Rate this:
Please Sign up or sign in to vote.
An article presenting a JavaScript implementation for calculating the volume of any polyhedron.

Sample Image

Introduction

Calculating the volume of regular and irregular polyhedra 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 problem, and presents a JavaScript implementation that allows the volumes of arbitrary polyhedra to be calculated using a form contained in a Web page. This JavaScript implementation allows a user to easily calculate the volumes of more interesting, unusual, and challenging polyhedra.

Background

Many practical applications of science and technology (including engineering, mathematics, computer science, and bioinformatics) require calculating the volumes of regular and irregular polyhedra. For example, an engineer may be required to calculate the volume of a manufactured component, a mathematician may want to calculate the volume contained inside an experimentally determined surface, a computer scientist may require the volume of a computer generated cloud, or a bioinformatician may need to determine the volume of a molecule displayed by a three-dimensional graphics system.

A polyhedron is a three dimensional shape enclosed by a finite number of faces. Each face is formed by a polygon. The faces meet along straight-line segments called edges, and the edges meet at points called vertices. A polyhedron with identical vertices and congruent faces is called a regular polyhedron. The Platonic solids are five convex, regular polyhedra: the four-faced regular tetrahedron, the six-faced cube, the eight faced octahedron, the twelve-faced dodecahedron, and the twenty-faced icosahedron. Any polyhedron which is not regular is said to be irregular. A simple example of an irregular polyhedron is a cube with one corner sliced off.

As a student of elementary mathematics, algebra, or geometry, you were probably taught to apply standard formulas to calculate the volumes of simple polyhedra such as the cube (V = s3), the rectangular solid (V = lwh), and the tetrahedron (V= (\/¯2 / 12) s³). When faced with the problem of finding the volume of a more complicated polyhedron that did not match one of these simple shapes, you were probably taught to decompose that complicated polyhedron into two or more simpler objects whose volumes could then be found using standard formulas.

The following screen shot displays a wireframe image of an irregular polyhedron. The base of the polyhedron is an irregular five-sided polygon, and each of that polygon's vertices connect to one of two other vertices near the top of the polyhedron. How would you go about finding the volume of this irregular polyhedron?

A non-intuitive approach to finding the volume of an arbitrary polyhedron is to decompose the polyhedron into a collection of pyramids that share a common peak (located inside or on the surface of the polyhedron). Then you can accumulate the volumes of those pyramids to find the volume of the original polyhedron. In order to apply this technique, the volume of each pyramid must be found. The volume of a general pyramid is bh/3, where b is the area of the base and h is the perpendicular distance from the base to the peak. The problem thus reduces to finding the area of each base and the height of each pyramid. The area of each base is the area of the corresponding face, and that area may be found in terms of the face vertex coordinates.

In all but the simplest problems, the procedure ultimately requires identifying the vertices defining the faces of the polyhedron, selecting an appropriate common point to represent the peak of each pyramid, using the vertices to find the area of each base, and evaluating the height of each pyramid. When this procedure is performed by hand, ample opportunities arise to unintentionally introduce computational errors and arrive at an incorrect answer. However, if the vertex coordinates are readily available, the process is simplified because it is then much easier to calculate the area of each face and the required height.

Three Elementary Problems

To set the stage for the JavaScript computations presented in this paper, it is helpful to consider the solutions to three elementary problems.

First, the volume of a unit cube may be found by decomposing the cube into six pyramids. Each face of the cube is the base of one of the pyramids, and the center of the cube is selected as the common peak. The area of each base is 1.0, and the perpendicular distance from each base to the peak is 0.5. The volume of each pyramid is 0.5/3, and the volume of the cube is 6(0.5/3) or 1.0. In this example, the pyramid base areas and perpendicular distances may found by inspection, and the coordinates of each vertex are not directly required.

Next, the volume of a rectangular solid having length l, width w, and height h measured along the x, y, and z axes may be found by decomposing that solid into 6 pyramids that share a common peak located at the center of the solid and having coordinates (l/2, w/2, h/2). The pyramids formed by the left and right faces have areas wh and height l/2. The pyramids formed by the front and back faces have areas lh and height w/2. The pyramids formed by the top and bottom faces have areas lw and height h/2. Accumulating the volumes of these pyramids yields the volume of the rectangular solid: again, the pyramid base areas and perpendicular distances may be found by inspection, and the coordinates of each vertex are not directly required.

V = 2(1/3)lhw/2 + 2(1/3)lhw/2 + 2(1/3)lwh/2 = lwh

Finally, the volume of a sphere having radius 1.0 may be approximated by decomposing that sphere into a very large number of very thin pyramids that share a common peak located at the center of the sphere. In the limiting case, the total volume of the pyramids is 1/3 times the total base area (4πr2) times the height of each pyramid, r, or (4/3)πr3. Calculating the exact volume of an approximate sphere whose surface is modeled by a small number of vertical and horizontal slices requires the base area of each approximating pyramid to be determined, and that does require knowledge of all the vertex coordinates.

Developing the JavaScript Implementation

JavaScript is a programming language primarily intended for adding interactivity to Web pages. However, JavaScript may also be used to perform mathematical computations and demonstrate essential programming concepts. The only tools required to develop and test JavaScript programs are a simple text editor like Notepad and a Web browser like Internet Explorer. JavaScript programs, or "scripts", are embedded in the HTML code of a Web page.

JavaScript allows a user to create and manipulate their own objects, in addition to using built-in objects available as part of the language. In that sense, JavaScript is said to be an "object-aware" language. JavaScript objects have properties, called parameters, and JavaScript objects can execute functions, called methods.

To implement a JavaScript solution to the polyhedron volume problem, it will be necessary to develop the code necessary to process several different kinds of objects. We will need to define a collection of vertices, use those vertices to define the polyhedron's faces, find the area of those faces, assign a common point to serve as the top of each face pyramid, and finally accumulate the volume of all the face pyramids. To provide a user interface, a form contained in a Web page will be used.

In the following sections, JavaScript source files for classes Point, Vector, Polygon, and Pyramid are presented, and the details of each class is briefly described. Ultimately, these supporting classes greatly simplify implementing a solution to the Polyhedron volume problem.

JavaScript Code for the Class Point

JavaScript allows a programmer to define new objects that extend the built-in Object class. An object that represents a three-dimensional point will be useful for storing vertex values. The file Point.js contains the JavaScript code that defines a new class named Point. The class Point extends the built-in Object class by adding three properties named x, y, and z, and assigning a value, printPoint (the name of a JavaScript function) to the existing toString property. To use that code in an HTML document, it is only necessary to insert the following line:

<script language="JavaScript" src="Point.js"></script>
// File: Point.js
//
// JavaScript functions for Point processing
//
// Point constructor
function Point(X,Y,Z)
{
   var p = new Object();
   p.x = X;
   p.y = Y;
   p.z = Z;
   p.toString = printPoint;
   return p;
}

// Implementation of toString() returns a String
function printPoint()
{
   return "Point: (" + this.x + "," + this.y + "," + this.z + ")";
}

Testing the Class Point

The following HTML document can be used to test the class, Point. The result should be a single line of output in the browser's window:

Point: (10,20,30)
<html>
<head>
<title>Test Class Point</title>
<script language="JavaScript" src="Point.cs"></script>
</head>
<body>
<script language="JavaScript">
   var a = new Point( 10, 20, 30 );
   document.write( a );
</script>
</body>
</html>

Note that the toString() method is used to display Point's value. The document.write() method automatically calls an object's toString() method. By defining that method for class Point, we can create a simply formatted string that displays a Point's coordinates. This approach is taken in the examples that follow. It provides an easy way to test each class.

JavaScript Code for the Class Vector

JavaScript code that defines a Vector object and the methods that implement vector processing, will be useful for processing vectors and finding the direction normal to a surface. The file Vector.js contains JavaScript that defines a new class named Vector. The class Vector extends the built-in Object class by adding three properties named x, y, and z, and assigning a value printVector (the name of a JavaScript function) to the existing toString property, and adding several new properties that define additional vector processing methods. To use that code in an HTML document it is only necessary to insert the following line:

<script language="JavaScript" src="Vector.js"></script>
// File: Vector.js
//
// JavaScript functions for Vector processing
//
// Vector constructor
function Vector(X,Y,Z)
{
   var p = new Object();
   p.x = X;
   p.y = Y;
   p.z = Z;
   p.toString = printVector;
   p.magnitude = getMagnitude;
   p.dotProduct = getDotProduct;
   p.crossProduct = getCrossProduct;
   p.unitVector = getUnitVector;
   p.subtract = subtractVectors;
   p.add = addVectors;
   return p;
}

// Implementation of toString() returns a String
function printVector()
{
   return "Vector: (" + this.x + "," + this.y + "," + this.z + ")";
}

// Vector magnitude
function getMagnitude()
{
   var sum = this.x*this.x + this.y*this.y + this.z*this.z;
   var result = 0.0;
   if( sum > 0.0 ) {
      result = Math.pow( sum, 0.5 );
   }
   else
      result = 0.0;
   return result;
}

// Vector dot product
function getDotProduct(B)
{
   var result = this.x * B.x + this.y * B.y + this.z * B.z;
   return result;
}

// Vector cross product
function getCrossProduct(B)
{
   var c = new Vector(0,0,0);
   c.x = this.y * B.z - B.y * this.z;
   c.y = this.z * B.x - B.z * this.x;
   c.z = this.x * B.y - B.x * this.y;
   return c;
}

// Vector unit vector
function getUnitVector()
{
   var mag = this.magnitude();
   
   if( mag <= 0.0 )
      alert("Error: Attempt to use mag <= 0 in getUnitVector()");
      
   var v = new Vector( this.x, this.y, this.z );
   v.x = v.x / mag;
   v.y = v.y / mag;
   v.z = v.z / mag;
   return v;
}

// Subtract two vectors
function subtractVectors(B)
{
   var u = new Vector( 0,0,0 );
   u.x = this.x - B.x;
   u.y = this.y - B.y;
   u.z = this.z - B.z;
   return u;
}

// Add two vectors
function addVectors(B)
{
   var u = new Vector( 0,0,0 );
   u.x = this.x + B.x;
   u.y = this.y + B.y;
   u.z = this.z + B.z;
   return u;
}

Testing the Class Vector

The following HTML document can be used to test the class Vector. The result should be the following lines of output in the browser's window:

a is Vector: (10,20,30)
b is Vector: (20,30,-10)
sum c is Vector: (30,50,20)
difference d is Vector: (-10,-10,40)
magnitude of a is 37.416573867739416
dot product (a * b) is 500
cross product (a x b) is Vector: (-1100,700,-100)
unit vector for Vector: (10,20,30) is Vector: 
   (0.2672612419124244,0.5345224838248488,0.8017837257372731)
magnitude of h is 1
<html>
<head>
<title>Test Class Vector</title>
<script language="JavaScript" src="Vector.js"></script>
</head>
<body>
<script language="JavaScript">
   var a = new Vector(10,20,30);
   var b = new Vector(20,30,-10);
   var c = a.add(b);
   var d = a.subtract(b);
   document.write("a is " + a + "<br>");
   document.write("b is " + b + "<br>");
   document.write("sum c is " + c + "<br>");
   document.write("difference d is " + d + "<br>");
   var e = a.magnitude();
   document.write("magnitude of a is " + e + "<br>");
   var f = a.dotProduct(b);
   document.write("dot product (a * b) is " + f + "<br>");
   var g = a.crossProduct(b);
   document.write("cross product (a x b) is " + g + "<br>");
   var h = a.unitVector();
   document.write("unit vector for " + a + " is " + h + "<br>");
   var i = h.magnitude();
   document.write("magnitude of h is " + i + "<br>");
</script>
</body>
</html>

JavaScript Code for the Class Polygon

The JavaScript code that defines a Polygon object and methods that implement finding the area and perimeter of a polygon, will also be useful. The file Polygon.js contains the JavaScript code that defines a new class named Polygon.

The class Polygon extends the built-in Object class. A Polygon is modeled by an array of vertices. The vertices are taken in counter-clockwise order around the polygon’s perimeter as you look at the face. A value, printPolygon (the name of a JavaScript function), is assigned to the existing toString property, and methods to calculate the area, perimeter, normal vector, and transformed coordinates of the polygon are also added. The normal vector will later be used to find the height of a pyramid, and the transformed coordinates will be used to find the polygon’s area.

To use that code in an HTML document it is only necessary to insert the following line:

<script language="JavaScript" src="Polygon.js"></script>
// File: Polygon.js
//
// JavaScript functions for Polygon processing
//
// Polygon constructor
function Polygon(a)
{
   var t = new Object();
   //t.points = a;
   t.points = new Array();
   for( k = 0; k < a.length; k++ )
      t.points[k] = a[k];
   t.toString = printPolygon;
   t.area = getPolygonArea;
   t.localCoordinates = getLocalCoordinates;
   t.normal = getNormal;
   return t;
}

// Implementation of toString()
function printPolygon()
{
   return "Polygon: " + this.points ;
}

// Calculate a polygon's area
function getPolygonArea()
{
   // Get the polygon in its own
   // x-y coordinates (all z's should be 0)
   var polygonPrime = this.localCoordinates();
      
   // Apply the surveyor's formula
   len = polygonPrime.points.length;
   
   var result = 0.0;
   var dx = 0.0;
   var dy = 0.0;
   for( var k = 0; k < (len-1); k++ )
   {
      dx = polygonPrime.points[k+1].x - polygonPrime.points[k].x;
      dy = polygonPrime.points[k+1].y - polygonPrime.points[k].y; 
      result += polygonPrime.points[k].x * dy - 
                polygonPrime.points[k].y * dx; 
   } 
   dx = polygonPrime.points[0].x - polygonPrime.points[len-1].x;
   dy = polygonPrime.points[0].y - polygonPrime.points[len-1].y; 
   result += polygonPrime.points[len-1].x * dy - 
             polygonPrime.points[len-1].y * dx;  
   return result/2.0;
}

// Calculate a polygon's normal vector
function getNormal()
{
   // Construct a vector from points[0] to points[1]
   var dx = this.points[1].x - this.points[0].x;
   var dy = this.points[1].y - this.points[0].y;
   var dz = this.points[1].z - this.points[0].z;
   var v01 = new Vector( dx,dy,dz );
   
   // Construct a vector from points[1] to points[2]
   dx = this.points[2].x - this.points[1].x;
   dy = this.points[2].y - this.points[1].y;
   dz = this.points[2].z - this.points[1].z;
   var v12 = new Vector( dx,dy,dz );   
   
   // Get the cross product, which returns
   // a vector in the normal direction
   norm = v01.crossProduct(v12);   
   
   // Make norm a unit vector
   norm = norm.unitVector();   
   
   return norm;
}

// Convert a Polygon in (x,y,z) to a polygon in (x',y',0)
function getLocalCoordinates()
{
   // Copy "this" Polygon
   var p = new Polygon( this.points );
   
   // Select p.points[0] as the displacement
   var Rx = p.points[0].x;
   var Ry = p.points[0].y;
   var Rz = p.points[0].z;

   // Subtract R from all the points of polygon p
   for( var k = 0; k < p.points.length; k++ )
   {
      p.points[k].x -= Rx;
      p.points[k].y -= Ry;
      p.points[k].z -= Rz;
   }

   // Select P0P1 as the x-direction
   var dx = p.points[1].x-p.points[0].x;
   var dy = p.points[1].y-p.points[0].y;
   var dz = p.points[1].z-p.points[0].z;
   var xprime = new Vector(dx,dy,dz);
   
   // Find a unit vector in the xprime direction
   var iprime = xprime.unitVector();

   // Find the vector P1P2
   dx = p.points[2].x-p.points[1].x;
   dy = p.points[2].y-p.points[1].y;
   dz = p.points[2].z-p.points[1].z;
   var p1p2 = new Vector(dx,dy,dz);

   // Find a vector kprime in the zprime direction
   var kprime = iprime.crossProduct(p1p2);
   
   // Make kprime a unitVector
   kprime = kprime.unitVector();

   // Find the vector jprime in the yprime direction
   var jprime = kprime.crossProduct(iprime);

   // For each point, calculate the projections on xprime, yprime, zprime
   // (All zprime values should be zero)
   for( var k = 0; k < p.points.length; k++ )
   {
      var pprime = new Point(0,0,0);
      var pv = new Vector( p.points[k].x, p.points[k].y, p.points[k].z );
      pprime.x = iprime.dotProduct(pv);
      pprime.y = jprime.dotProduct(pv);
      pprime.z = kprime.dotProduct(pv);
      p.points[k] = pprime;
   }

   // Return a polygon in its own local x'y'z' coordinates
   return p;
}

Testing the Class Polygon

The following HTML document can be used to test the class Polygon. The result should be the following lines of output in the browser's window:

poly1 is Polygon: Point: (0,0,0), 
         Point: (1,0,0),Point: (1,2,0),Point: (0,1,0)
area: 1.5
<html>
<head>
<title>Test Class Polygon</title>
<script language="JavaScript" src="Point.js"></script>
<script language="JavaScript" src="Vector.js"></script>
<script language="JavaScript" src="Polygon.js"></script>
</head>
<body>
<script language="JavaScript">
   var p0 = new Point(0,0,0);
   var p1 = new Point(1,0,0);
   var p2 = new Point(1,2,0);
   var p3 = new Point(0,1,0);
   var points = new Array();
   points[0] = p0;
   points[1] = p1;
   points[2] = p2;
   points[3] = p3;
   var poly1 = new Polygon(points);
   document.write("poly1 is " + poly1 + "<br>");
   var a = poly1.area();
   document.write("area: " + a + "<br>");
</script>
</body>
</html>

JavaScript Code for the Class Pyramid

The JavaScript code that defines a Pyramid object and a method that implements finding the volume of a pyramid, will be useful for finding the volume of a polyhedron. The file Pyramid.js contains the JavaScript code that defines a new class named Pyramid.

The class Pyramid extends the built-in Object class. A Pyramid is modeled by a Polygon, the base of the Pyramid, and a Point, the peak of the Pyramid. A value, printPyramid (the name of a JavaScript function), is assigned to the existing toString property, and methods to calculate the volume and height of the Pyramid have been added.

To use that code in an HTML document, it is only necessary to insert the following line:

<script language="JavaScript" src="Pyramid.js"></script>
// File: Pyramid.js
//
// JavaScript functions for Pyramid processing
//
// Pyramid constructor
function Pyramid(poly,pnt)
{
   var t = new Object();
   t.polygon = poly;
   t.point = pnt;
   t.height = getPyramidHeight
   t.volume = getPyramidVolume;
   t.baseArea = getPyramidBaseArea;
   t.toString = printPyramid;
   return t;
}

// Implementation of toString() returns a String
function printPyramid()
{
   return "Pyramid: " + this.polygon + " + " + this.point;
}

// Calculate the Pyramid's volume
function getPyramidVolume()
{
   // Calculate the perpendicular distance
   // from the base to the top point
   var d = this.height();
 
   // Calculate the area of the base
   var baseArea = this.polygon.area();

   // Calculate the volume of the polygon's pyramid
   var volume = d * baseArea / 3.0;
   return volume;   
}

function getPyramidHeight()
{
   // Construct a vector from the Pyramid base to the top point
   var dx = this.point.x - this.polygon.points[0].x;
   var dy = this.point.y - this.polygon.points[0].y;
   var dz = this.point.z - this.polygon.points[0].z;
   var vt = new Vector(dx,dy,dz);   

   // Calculate the perpendicular
   // distance from the base to the top point.
   // The distance d is the projection of vt in the normal direction.
   // Because a right-hand coordinate system is assumed, the value of d
   // may be negative, so the absolute value is returned.
   var norm = this.polygon.normal();    
   var d = norm.dotProduct(vt);
   var result = 0.0; 
   if( d < 0.0 )
      result = Math.abs(d);
   else
      result = d;
   return result;
}

function getPyramidBaseArea()
{
   return this.polygon.area();
}

Testing the Class Pyramid

The following HTML document can be used to test the class Pyramid. The result should be the following lines of output in the browser's window:

pyramid is Pyramid: Polygon: Point: (0,0,0), 
        Point: (1,0,0),Point: (1,2,0),
        Point: (0,1,0) + Point: (0.5,0.5,1)
pyramid height is: 1
pyramid base area is: 1.5
pyramid volume: 0.5
<html>
<head>
<title>Test Class Pyramid</title>
<script language="JavaScript" src="Point.js"></script>
<script language="JavaScript" src="Vector.js"></script>
<script language="JavaScript" src="Polygon.js"></script>
<script language="JavaScript" src="Pyramid.js"></script>
</head>
<body>
<script language="JavaScript">
   var p0 = new Point(0,0,0);
   var p1 = new Point(1,0,0);
   var p2 = new Point(1,2,0);
   var p3 = new Point(0,1,0);
   var points = new Array();
   points[0] = p0;
   points[1] = p1;
   points[2] = p2;
   points[3] = p3;
   var poly = new Polygon(points);
   var pnt = new Point(0.5,0.5,1);
   var pyramid = new Pyramid(poly,pnt);
   document.write("pyramid is " + pyramid + "<br>");
   document.write("pyramid height is: " + pyramid.height() + "<br>" );
   document.write("pyramid base area is: " + pyramid.baseArea() + "<br>" );
   document.write("pyramid volume: " + pyramid.volume() + "<br>");
</script>
</body>
</html>

Putting it All Together - Implementing the Polyhedron Volume Calculator

The following HTML code contains a form that allows a user to define a polyhedron by specifying the number of faces, the vertices that define each face, and each vertex’s coordinates. The form contains a Submit button that, when clicked, triggers the execution of the JavaScript function named calculate(). That function reads the user’s input, parses the vertex coordinate values, calculates the pyramid volume associated with each face, accumulates the polyhedron’s total volume, and displays that result using a specified number of decimal digits. As designed, the form can handle up to 9 faces and up to 12 vertices. The form’s design can be extended to handle problems involving more faces and more vertices. The JavaScript code must then be modified to initialize, read, and process any additional data.

For test and demonstration purposes, the form also contains an additional button labeled Load Cube. When that button is clicked, the JavaScript function named loadCube() executes and fills the form with the face and vertex data for a unit cube. If the Calculate button is then clicked, the volume of the unit cube is calculated and displayed as 1.00000. In the calculate() method, the number of displayed digits is controlled by applying the toFixed() method.

The form is initially loaded with sample data defining a unit cube having one corner cut off. Clicking the Reset button reloads that sample data, and if the Calculate button is then clicked, the volume of that irregular polyhedron is displayed as 0.97197.

<html>
<head>
<title>Polyhedron Volume Calculator</title>

<style>
<!--
body {background-color:#FF9900;}
table {background-color:#FF9900;}
.content {width:800px; background-color:white; padding:10px;}
-->
</style>

<script language="JavaScript" src="Point.js"></script>
<script language="JavaScript" src="Vector.js"></script>
<script language="JavaScript" src="Polygon.js"></script>
<script language="JavaScript" src="Pyramid.js"></script>
<script language="JavaScript">

// Button click event handler
function calculate()
{
    // Read the number of faces and vertices
    var faces = parseInt(document.getElementById("FACES").value);
    var vertices = parseInt(document.getElementById("VERTICES").value);
    
    // Read all the vertex coordinates
    var vertex = new Array(); 
    for( var k = 0; k < vertices; k++ )
    {
        var vertexStr = document.getElementById("VERTEX"+k).value; 
        var items = vertexStr.split(","); 
        vertex[k] = new Point( parseFloat(items[0]), 
                    parseFloat(items[1]), parseFloat(items[2])); 
    }

    // Process all the faces
    var totalVolume = 0.0;
    for( var k = 0; k < faces; k++ )
    {
        // Read the index numbers of the vertices for this face
        var str = document.getElementById("FACEVERTICES" + k).value;
        var indexStrings = str.split(",");
        var indexNumbers = new Array();
        for( var j = 0; j < indexStrings.length; j++ )
        indexNumbers[j] = parseInt(indexStrings[j]); 

        // Create an array of Points using the indexNumbers
        verts = new Array();
        for( var j = 0; j < indexNumbers.length; j++ )
        { 
            var index = indexNumbers[j];
            var x = vertex[index].x;
            var y = vertex[index].y;
            var z = vertex[index].z;
            verts[j] = new Point( x,y,z );
        }

        // Create a Polygon using the vertices
        var poly = new Polygon( verts );

        // Create a Pyramid using the Polygon
        //var pyrm = new Pyramid( poly, new Point(0.5,0.5,1.0) );
        // Create a Pyramid using the face Polygon and vertex[0]
        var pyrm = new Pyramid( poly, vertex[0] );

        // Get he Pyramid volume
        var vol = pyrm.volume();

        totalVolume += vol;
    } 

    // Display the calculated volume
    document.getElementById("VOLUME").value = totalVolume.toFixed(5);
}

function loadCube()
{
    document.getElementById("FACES").value = "6";
    document.getElementById("VERTICES").value = "8";

    document.getElementById("FACEVERTICES0").value = "0,1,2,3";
    document.getElementById("FACEVERTICES1").value = "4,5,6,7";
    document.getElementById("FACEVERTICES2").value = "0,3,5,4";
    document.getElementById("FACEVERTICES3").value = "1,7,6,2";
    document.getElementById("FACEVERTICES4").value = "2,6,5,3";
    document.getElementById("FACEVERTICES5").value = "0,4,7,1";
    document.getElementById("FACEVERTICES6").value = "";
    document.getElementById("FACEVERTICES7").value = "";
    document.getElementById("FACEVERTICES8").value = "";

    document.getElementById("VERTEX0").value = "0,0,0";
    document.getElementById("VERTEX1").value = "1,0,0";
    document.getElementById("VERTEX2").value = "1,0,1";
    document.getElementById("VERTEX3").value = "0,0,1";
    document.getElementById("VERTEX4").value = "0,1,0";
    document.getElementById("VERTEX5").value = "0,1,1";
    document.getElementById("VERTEX6").value = "1,1,1";
    document.getElementById("VERTEX7").value = "1,1,0";
    document.getElementById("VERTEX8").value = "";
    document.getElementById("VERTEX9").value = "";
    document.getElementById("VERTEX10").value = "";
    document.getElementById("VERTEX11").value = "";

    document.getElementById("VOLUME").value = "";
}
</script>
</head>
<body>

<div align="center">
<div class="content">

<form>
<table border="2" cellspacing="1" 
          id="AutoNumber1" 
          bgcolor="#FF9900" cellpadding="2">
<tr>
<td colspan="4" align="center">
<h2>Polyhedron Volume Calculator</h2>
</td>
</tr>
<tr>
<td colspan="2">Faces: 
<input type="text" name="FACES" 
          id="FACES" size="10" 
          value="7"></td>
<td colspan="2">Vertices:
<input type="text" name="VERTICES" 
          id="VERTICES" size="10" 
          value="10"></td>
</tr>
<tr>
<td align="center">Face</td>
<td align="center">Vertices</td>
<td align="center">Vertex</td>
<td align="center">Coordinates</td>
</tr>
<tr>
<td align="center">0</td>
<td>
<input type="text" name="FACEVERTICES0" id="FACEVERTICES0" size="10" 
          value="0,1,2,3,4"></td>
<td align="center">0</td>
<td> <input type="text" name="VERTEX0" 
                     id="VERTEX0" size="10" 
                     value="0,0,0"></td>
</tr>
<tr>
<td align="center">1</td>
<td>
<input type="text" name="FACEVERTICES1" id="FACEVERTICES1" 
         size="10" value="6,9,8,7"></td>
<td align="center">1</td>
<td> <input type="text" name="VERTEX1" 
        id="VERTEX1" size="10" value="1,0,0"></td>
</tr>
<tr>
<td align="center">2</td>
<td>
<input type="text" name="FACEVERTICES2" 
        id="FACEVERTICES2" size="10" value="0,4,9,6"></td>
<td align="center">2</td>
<td> 
<input type="text" name="VERTEX2" 
        id="VERTEX2" size="10" value="1,0,0.5"></td>
</tr>
<tr>
<td align="center">3</td>
<td>
<input type="text" name="FACEVERTICES3" 
          id="FACEVERTICES3" size="10" value="1,7,8,5,2"></td>
<td align="center">3</td>
<td> 
<input type="text" name="VERTEX3" id="VERTEX3" 
          size="10" value="0.5,0,1"></td>
</tr>
<tr>
<td align="center">4</td>
<td>
<input type="text" name="FACEVERTICES4" 
          id="FACEVERTICES4" size="10" value="4,3,5,8,9"></td>
<td align="center">4</td>
<td> 
<input type="text" name="VERTEX4" id="VERTEX4" 
          size="10" value="0,0,1"></td>
</tr>
<tr>
<td align="center">5</td>
<td>
<input type="text" name="FACEVERTICES5" 
       id="FACEVERTICES5" size="10" value="0,6,7,1"></td>
<td align="center">5</td>
<td> 
<input type="text" name="VERTEX5" id="VERTEX5" 
         size="10" value="1,0.5,1"></td>
</tr>
<tr>
<td align="center">6</td>
<td>
<input type="text" name="FACEVERTICES6" 
          id="FACEVERTICES6" size="10" value="2,5,3"></td>
<td align="center">6</td>
<td> 
<input type="text" name="VERTEX6" id="VERTEX6" 
          size="10" value="0,1,0"></td>
</tr>
<tr>
<td align="center">7</td>
<td>
<input type="text" name="FACEVERTICES7" 
          id="FACEVERTICES7" size="10"></td>
<td align="center">7</td>
<td> 
<input type="text" name="VERTEX7" id="VERTEX7" 
           size="10" value="1,1,0"></td>
</tr>
<tr>
<td align="center">8</td>
<td>
<input type="text" name="FACEVERTICES8" 
        id="FACEVERTICES8" size="10"></td>
<td align="center">8</td>
<td>
<input type="text" name="VERTEX8" id="VERTEX8" 
           size="10" value="1,1,1"></td>
</tr>
<tr>
<td align="center">&nbsp;</td>
<td>&nbsp;</td>
<td align="center">9</td>
<td>
<input type="text" name="VERTEX9" id="VERTEX9" 
          size="10" value="0,1,1"></td>
</tr>
<tr>
<td align="center">&nbsp;</td>
<td>&nbsp;</td>
<td align="center">10</td>
<td>
<input type="text" name="VERTEX10" 
         id="VERTEX10" size="10"></td>
</tr>
<tr>
<td align="center">&nbsp;</td>
<td>&nbsp;</td>
<td align="center">11</td>
<td>
<input type="text" name="VERTEX11" 
         id="VERTEX11" size="10"></td>
</tr>
<tr>
<td align="center">&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td colspan="2">
<p align="right">Volume: </td>
<td colspan="2"><input type="text" 
       name="VOLUME" id="VOLUME" size="20"></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" value="Calculate" onClick="calculate()"></td>
<td colspan="2" align="center">
<input type="reset" value="Reset" name="B1"></td>
</tr>
<tr>
<td colspan="4" align="center">
<input type="button" value="Load Cube" 
          onClick="loadCube()" name="B2"></td>
</tr>
</table>
</form>

</div>
</div>
</body>
</html>

A Specific Example

The following screen shot displays a wire-frame image of an irregular polyhedron. Using the Polyhedron Volume Calculator, the volume of this irregular polyhedron can easily be found. The required data is tabulated below. The volume of this unusual shape is 20.36364, to five significant digits.

Vertex Co-ordinates Face Vertices
0 0, 0, 0 1 0, 1, 2, 3, 4
1 0, 2, 0 2 4, 5, 0
2 1, 4, 0 3 0, 5, 6, 1
3 4, 2, 0 4 1, 6, 2
4 2, 0, 0 5 3, 2, 6
5 2, 1, 4 6 5, 4, 3, 6
6 2, 2, 6  --- ---

For comparison, the volume of a circular cone with a base area of 10.0 and a height of 6.0 is 1/3*10*6, or 20.0 cubic units.

Summary

The problem of finding the volume of an irregular polyhedron and the solution of that problem by decomposing the polyhedron into a collection of pyramids was discussed. Three simple problems involving the volume of a cube, a rectangular solid, and a sphere were presented to set the stage for solving more difficult problems.

JavaScript source files for classes Point, Vector, Polygon, and Pyramid were presented. The result is a library of JavaScript source files that may easily be included in other HTML documents.

The code for an HTML document containing a form that allows a user to enter a polyhedron’s face vertices and vertex coordinates was presented. The JavaScript code within that document calculates the volume of a polyhedron given a list of its faces, the vertices comprising each face, and the coordinates of each vertex. The form is initially loaded with sample data for calculating the volume of a unit cube (a simple regular polyhedron). For demonstration purposes, the data for a unit cube having a corner cut off (a simple example of an irregular polyhedron) can also be loaded.

The article concluded with an example that calculated the volume of an irregular polyhedron, a wedge-like shape having an irregular polygon with fve sides for a base.

References

More information regarding the mathematics underlying the code in this article may be found in these references:

  1. Weisstein, E. W.,. "Polyhedron" From MathWorld--A Wolfram Web Resource
  2. Weast, R. C., Editor, 1968, CRC Standard Mathematical Tables, 16th Edition, (Cleveland: The Chemical Rubber Co.)
  3. Kreyszig, E., 1967, Advanced Engineering Mathematics, 2nd Edition, (New York: John Wiley and Sons, Inc.)
  4. Estrella, S.G., 2002, The Web Wizard’s Guide to JavaScript, (Boston: Addison Wesley)
  5. Negrino, T. and Smith, D, 1998, JavaScript for the World Wide Web, 2nd Edition, (Berkely: Peachpit Press)

Other CodeProject articles concerning JavaScript object-oriented programming include:

History

  • 03-31-2006:
    • Original article.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

dszarkow
Retired Top Software Tutor
United States United States
Don Szarkowicz retired after 18 years teaching introductory and advanced programming and application development courses for the Department of Computer Information Systems at Indiana University Northwest.
 
He currently operates Top Software Tutor, which offers affordable, personalized, one-on-one assistance for a broad range of computing projects, homework problems and other assignments involving popular programming languages, Web design and development techniques, and Microsoft Office applications
 
His technical interests include Web programming and C# using Visual Studio NET.
 
Don holds a Ph.D. in Electrical Engineering from the Illinois Institute of Technology, and an MBA from the University of Chicago. Don is also a registered Professional Engineer and an amateur radio operator (call sign KC9ALE).

Comments and Discussions

 
GeneralA bug in calculate() PinmemberSamZhen7-Aug-08 12:58 
GeneralExtra Faces Pinmemberpeterkugl6-Mar-08 7:00 
GeneralRe: Extra Faces Pinmemberdszarkow8-Mar-08 11:21 
GeneralRe: Extra Faces Pinmemberpeterkugl12-Mar-08 4:23 
Questionfour sided faces and excess faces Pinmemberpeterkugl6-Mar-08 6:16 
Hello Professor,
 
I'm a civil engineer and one of your end users.
 
I'm trying to estimate debris volumes in a small reservoir. I guess first I've generated a little model with 12 faces and 10 vertices. As far as I can tell that would be too many for your program (no space to put in that many faces).
 
Secondly, more generally, how does your program handle faces with more than 3 vertices where the points in excess of 3 don't lie on a plane. I have two faces, the water surface and the dam face with 5 vertices that are defined flat by the vertices. But other points along the bottom are variable and generate faces that aren't necessarily flat.
 
I could simplify my model, but I've grown fond of this one and don't see why the theory behind this program would stop at x number of faces. I would triangulate everything myself if I had the room to do it.
 
Anyway, thank you very much for reading my long message.
Any info would be great,
Yours truly,
Peter Kuglstatter, P.E.
 
Water Resource Engineer

GeneralGreat article PinmemberJubjub3-Apr-06 17:06 
GeneralRe: Great article Pinmemberdszarkow4-Apr-06 1:59 
GeneralRe: Great article Pinmemberabyzmic11-Apr-06 4:59 
GeneralRe: Great article Pinmemberdszarkow14-Apr-06 12:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 3 Apr 2006
Article Copyright 2006 by dszarkow
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid