65.9K
CodeProject 正在变化。 阅读更多。
Home

多面体体积计算 - JavaScript 实现

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (9投票s)

2006年4月3日

13分钟阅读

viewsIcon

100460

downloadIcon

907

本文介绍了一个用于计算任何多面体体积的 JavaScript 实现。

Sample Image

引言

计算规则和不规则多面体的体积在科学和技术的几乎所有分支中都占有重要地位,包括工程、数学、计算机科学和生物信息学。本文简要概述了这个问题,并提供了一个 JavaScript 实现,该实现允许使用网页中的表单来计算任意多面体的体积。此 JavaScript 实现使用户能够轻松计算更具趣味性、不寻常且具有挑战性的多面体的体积。

背景

科学和技术的许多实际应用(包括工程、数学、计算机科学和生物信息学)都需要计算规则和不规则多面体的体积。例如,工程师可能需要计算制成品体积,数学家可能想计算实验确定的表面所包含的体积,计算机科学家可能需要计算计算机生成的点云的体积,或者生物信息学家可能需要确定三维图形系统显示的分子体积。

多面体是由有限数量的面围成的三维形状。每个面由一个多边形形成。面沿着称为棱的直线段相交,棱在称为顶点的点处相交。具有相同顶点和全等面的多面体称为规则多面体。柏拉图立体是五种凸的规则多面体:四面体的正四面体,六面体的立方体,八面体的正八面体,十二面体的正十二面体,以及二十面体的正二十面体。任何不规则的多面体都称为不规则多面体。不规则多面体的一个简单例子是切掉一个角的立方体。

作为初等数学、代数或几何学的学生,您可能被教导使用标准公式来计算简单多面体的体积,例如立方体(V = s3)、长方体(V = lwh)和四面体(V= (\/¯2 / 12) s³)。当面临计算一个不符合这些简单形状的更复杂多面体的体积时,您可能被教导将该复杂多面体分解为两个或多个更简单的对象,然后使用标准公式计算它们的体积。

以下屏幕截图显示了一个不规则多面体的线框图像。多面体的底面是一个不规则的五边形,该多边形的每个顶点都连接到多面体顶部附近的另外两个顶点之一。您将如何着手计算这个不规则多面体的体积?

计算任意多面体体积的一个非直观的方法是将多面体分解为一组以共同顶点(位于多面体内部或表面)为顶点的金字塔。然后,您可以累积这些金字塔的体积来找到原始多面体的体积。为了应用此技术,必须找到每个金字塔的体积。一般金字塔的体积是 bh/3,其中 b 是底面积,h 是从底面到底部的垂直距离。问题因此归结为找到每个底面的面积和每个金字塔的高度。每个底面的面积是相应面的面积,该面积可以根据面的顶点坐标找到。

在除最简单的问题之外的所有问题中,该过程最终需要识别定义多面体面的顶点,选择一个合适的共同点作为每个金字塔的顶点,使用顶点找到每个底面的面积,并计算每个金字塔的高度。当手工执行此过程时,很容易无意中引入计算错误并得出不正确的结果。然而,如果顶点坐标易于获得,则该过程会得到简化,因为此时更容易计算每个面的面积和所需的高度。

三个基本问题

为了铺垫本文提出的 JavaScript 计算,考虑三个基本问题的解决方案是有帮助的。

首先,可以通过将单位立方体分解为六个金字塔来找到单位立方体的体积。立方体的每个面是一个金字塔的底面,立方体的中心被选作共同顶点。每个底面的面积是 1.0,每个底面到底部的垂直距离是 0.5。每个金字塔的体积是 0.5/3,立方体的体积是 6(0.5/3) 或 1.0。在此示例中,可以通过观察找到金字塔底面积和垂直距离,并且不直接需要每个顶点的坐标。

接下来,长、宽、高分别为 lwh 的长方体的体积,可以将其分解为 6 个金字塔来找到,这些金字塔以位于长方体中心且坐标为 (l/2, w/2, h/2) 的共同顶点为顶点。由左右面形成的金字塔具有面积 wh 和高度 l/2。由前后面形成的金字塔具有面积 lh 和高度 w/2。由顶面和底面形成的金字塔具有面积 lw 和高度 h/2。累积这些金字塔的体积即可得到长方体的体积:同样,可以通过观察找到金字塔底面积和垂直距离,并且不直接需要每个顶点的坐标。

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

最后,半径为 1.0 的球体的体积可以通过将其分解为大量的非常薄的金字塔来近似,这些金字塔以球体中心为共同顶点。在极限情况下,金字塔的总体积是底面积 (4πr2) 乘以每个金字塔的高度 r 的 1/3,即 (4/3)πr3。计算一个表面由少量垂直和水平切片建模的近似球体的精确体积需要确定每个近似金字塔的底面积,这确实需要知道所有顶点坐标。

开发 JavaScript 实现

JavaScript 是一种主要用于为网页添加交互性的编程语言。但是,JavaScript 也可用于执行数学计算和演示基本编程概念。开发和测试 JavaScript 程序所需的唯一工具是像记事本这样的简单文本编辑器和像 Internet Explorer 这样的网页浏览器。JavaScript 程序或“脚本”嵌入在网页的 HTML 代码中。

JavaScript 允许用户创建和操作自己的对象,以及使用作为语言一部分的内置对象。从这个意义上说,JavaScript 被称为“面向对象”的语言。JavaScript 对象具有称为参数的属性,并且 JavaScript 对象可以执行称为方法的函数。

为了实现多面体体积问题的 JavaScript 解决方案,有必要开发处理几种不同类型对象的代码。我们将需要定义一个顶点集合,使用这些顶点定义多面体的面,找到这些面的面积,指定一个共同点作为每个面金字塔的顶点,最后累积所有面金字塔的体积。为了提供用户界面,将使用网页中的表单。

在接下来的章节中,将介绍 PointVectorPolygonPyramid 类的 JavaScript 源文件,并简要描述每个类的详细信息。最终,这些支持类极大地简化了多面体体积问题的解决方案的实现。

Point 类的 JavaScript 代码

JavaScript 允许程序员定义扩展内置 Object 类的对象。表示三维点的对象将有助于存储顶点值。文件 Point.js 包含定义名为 Point 的新类的 JavaScript 代码。Point 类通过添加三个名为 xyz 的属性来扩展内置 Object 类,并将一个值 printPoint(一个 JavaScript 函数的名称)赋给现有的 toString 属性。要在 HTML 文档中使用该代码,只需插入以下行

<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 + ")";
}

测试 Point 类

以下 HTML 文档可用于测试 Point 类。结果应在浏览器窗口中显示一行输出

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>

请注意,toString() 方法用于显示 Point 的值。document.write() 方法会自动调用对象的 toString() 方法。通过为 Point 类定义该方法,我们可以创建一个简单的格式化字符串来显示 Point 的坐标。在接下来的示例中也采用了这种方法。它提供了一种测试每个类的简单方法。

Vector 类的 JavaScript 代码

定义 Vector 对象和实现向量处理方法的 JavaScript 代码,将有助于处理向量和找到表面的法线方向。文件 Vector.js 包含定义名为 Vector 的新类的 JavaScript 代码。Vector 类通过添加三个名为 xyz 的属性来扩展内置 Object 类,并将一个值 printVector(一个 JavaScript 函数的名称)赋给现有的 toString 属性,并添加了几个定义其他向量处理方法的新属性。要在 HTML 文档中使用该代码,只需插入以下行

<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;
}

测试 Vector 类

以下 HTML 文档可用于测试 Vector 类。结果应在浏览器窗口中显示以下几行输出

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>

Polygon 类的 JavaScript 代码

定义 Polygon 对象和实现查找多边形面积和周长的方法的 JavaScript 代码也将非常有用。文件 Polygon.js 包含定义名为 Polygon 的新类的 JavaScript 代码。

Polygon 类扩展了内置的 Object 类。Polygon 由一个顶点数组建模。当从多边形外部观察面时,顶点按逆时针顺序排列。一个值 printPolygon(一个 JavaScript 函数的名称)被赋给现有的 toString 属性,并且还添加了计算多边形的面积、周长、法向量和变换坐标的方法。法向量将用于查找金字塔的高度,变换坐标将用于查找多边形的面积。

要在 HTML 文档中使用该代码,只需插入以下行

<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;
}

测试 Polygon 类

以下 HTML 文档可用于测试 Polygon 类。结果应在浏览器窗口中显示以下几行输出

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>

Pyramid 类的 JavaScript 代码

定义 Pyramid 对象和实现查找金字塔体积的方法的 JavaScript 代码,将有助于查找多面体的体积。文件 Pyramid.js 包含定义名为 Pyramid 的新类的 JavaScript 代码。

Pyramid 类扩展了内置的 Object 类。Pyramid 由一个 PolygonPyramid 的底面)和一个 PointPyramid 的顶点)建模。一个值 printPyramid(一个 JavaScript 函数的名称)被赋给现有的 toString 属性,并且还添加了计算 Pyramid 体积和高度的方法。

要在 HTML 文档中使用该代码,只需插入以下行

<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();
}

测试 Pyramid 类

以下 HTML 文档可用于测试 Pyramid 类。结果应在浏览器窗口中显示以下几行输出

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>

整合起来 - 实现多面体体积计算器

以下 HTML 代码包含一个表单,允许用户通过指定面的数量、定义每个面的顶点以及每个顶点的坐标来定义多面体。该表单包含一个 Submit 按钮,单击该按钮将触发名为 calculate() 的 JavaScript 函数的执行。该函数读取用户的输入,解析顶点坐标值,计算与每个面相关的金字塔体积,累积多面体的总体积,并以指定的十进制数字位数显示该结果。按设计,该表单最多可以处理 9 个面和 12 个顶点。该表单的设计可以扩展以处理涉及更多面和更多顶点的问题。然后必须修改 JavaScript 代码以初始化、读取和处理任何其他数据。

出于测试和演示目的,该表单还包含一个标有 Load Cube 的附加按钮。单击此按钮时,名为 loadCube() 的 JavaScript 函数将执行,并用单位立方体的面和顶点数据填充表单。如果然后单击 Calculate 按钮,将计算单位立方体的体积并显示为 1.00000。在 calculate() 方法中,显示位数的数量由应用 toFixed() 方法控制。

表单最初加载了定义一个切掉一个角的单位立方体的示例数据。单击 Reset 按钮将重新加载该示例数据,然后单击 Calculate 按钮,将显示该不规则多面体的体积为 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>

具体示例

以下屏幕截图显示了一个不规则多面体的线框图像。使用多面体体积计算器,可以轻松找到这个不规则多面体的体积。所需数据如下表所示。这种不寻常形状的体积为 20.36364,精确到五位有效数字。

顶点 坐标 顶点
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  --- ---

相比之下,底面积为 10.0、高为 6.0 的圆锥体积为 1/3*10*6,即 20.0 立方单位。

摘要

讨论了计算不规则多面体体积的问题以及通过将多面体分解为一组金字塔来解决该问题。为了解决更困难的问题,提出了三个涉及立方体、长方体和球体体积的基本问题。

提出了 PointVectorPolygonPyramid 类的 JavaScript 源文件。结果是一个 JavaScript 源文件库,可以轻松地包含在其他 HTML 文档中。

提出了一个包含表单的 HTML 文档的代码,该表单允许用户输入多面体的面顶点和顶点坐标。该文档中的 JavaScript 代码根据其面、构成每个面的顶点以及每个顶点的坐标列表计算多面体的体积。该表单最初加载了用于计算单位立方体(一个简单的规则多面体)体积的示例数据。出于演示目的,还可以加载一个切掉一个角的单位立方体(一个不规则多面体的简单示例)的数据。

文章最后提供了一个计算不规则多面体体积的例子,该多面体是一个楔形形状,其底面是一个具有五个边的不规则多边形。

参考文献

有关本文代码背后数学的更多信息,请参阅以下参考文献

  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)

其他关于 JavaScript 面向对象编程的 CodeProject 文章包括

历史

  • 03-31-2006:
    • 原始文章。
© . All rights reserved.