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

测量员公式的 JavaScript 实现

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (11投票s)

2006年3月17日

5分钟阅读

viewsIcon

130627

downloadIcon

493

本文介绍了一个使用 Surveyor's formula 计算任意多边形面积的 JavaScript 实现。

Polygon Area and Perimeter Calculator Form

引言

计算多边形的面积(和周长)在科学和技术的几乎所有分支中都是一项重要任务,包括工程、数学、计算机科学和生物信息学。本文简要概述了 Surveyor’s formula,并提供了一个 JavaScript 实现,允许用户通过网页中的表单计算任意多边形的面积。使用此 JavaScript 实现,用户可以轻松计算更多有趣、不寻常和具有挑战性的多边形的面积。该代码还可以使用任何额外数据来计算多边形的周长。

背景

科学和技术的许多实际应用(包括工程、数学、计算机科学和生物信息学)都需要计算规则和不规则多边形的面积。例如,工程师可能需要计算不规则形状的面积以确定该形状的惯性矩,数学家可能想要知道 x 轴与实验确定的曲线之间的面积,计算机科学家可能需要某些程序生成的图形对象的面积,或者生物信息学家可能对数字图像中显示的细胞的面积感兴趣。

多边形是具有三个或更多边的平面图形。三角形、正方形、梯形和平行四边形是熟悉的多边形。更一般地说,由三个或更多直线段首尾相连形成的封闭图形也是多边形。多边形的边称为“边”,边相遇的点称为“顶点”。

作为初等数学、代数或几何学的学生,你可能被教导过使用标准公式来计算规则多边形(如等边三角形、正方形、五边形和六边形)的面积。你也可能学过如何计算更简单的不规则多边形(如三角形、矩形、梯形和平行四边形)的面积。这些问题很重要,因为在自然界中可以找到规则和不规则多边形的例子。当面临一个更复杂的多边形,不符合这些标准形状时,你可能被教导过将这个复杂多边形分解成两个或多个更简单的形状,然后使用标准公式计算它们的面积。

这是一张不规则多边形的图片。你会如何计算这个图形的面积?

为了应用标准公式,必须找到更简单形状的长度、宽度或高度,并且在除最简单的问题之外的所有问题中,这个过程最终需要找到每个顶点的坐标,然后使用这些坐标计算所需的距离。当手工执行此过程时,很容易无意中引入计算错误并得出错误答案。

然而,如果多边形的顶点坐标很容易找到(可能通过从比例图上读取),或者这些坐标以其他方式可用,则无需分解,并且可以使用 Surveyor’s formula 精确计算多边形的面积。

如果多边形由一组标记为 P0, P1, ..., Pn-1 的 n 个顶点描述,并且从任何初始顶点以逆时针方向标识,并且每个 Pk 的坐标为 (xk,yk),则 Surveyor’s formula 可以简单地写成:

A = (x0y1 + x1y2 + ... + xn-1y0 - y0x1 - y1x2 - ... - yn-1x0) / 2

如果我们赋值 Pn = P0,并且增量 dxk 和 dyk 是测量到下一个顶点的距离,则

dyk = yk+1 - yk, dxk = xk+1 - xk

Surveyor's formula 也可以写成:

A = x0dy0 - y0dx0 + x1dy1 - y1dx1 + ... + xn-1dyn-1 - yn-1dxn-1

为了在 JavaScript 中实现 Surveyor's formula,我们将编写一个函数来读取和存储顶点的数量以及每个顶点的 x 和 y 坐标,第二个函数来计算并返回多边形的封闭面积,第三个函数来计算并返回多边形的周长,第四个函数作为事件处理程序并控制整个过程。

实现和代码

以下 JavaScript/HTML 代码定义了一个文档,其中包含一个表单,允许用户通过输入顶点的数量和每个顶点的坐标来指定多边形的形状。表单包含一个“计算”按钮,单击该按钮时将执行名为 handleCalculate() 的 JavaScript 函数。该函数进而调用 readUserData()calculateArea()calculatePerimeter()displayCoordinates() 函数来读取用户输入,解析坐标值,计算多边形的面积和周长,并使用指定的十进制位数显示结果。在此示例中,最多可以输入 10 个顶点。如果涉及更多顶点,则必须在表单的表中添加具有 ID X10、X11、... 的文本框的其他行。将读取顶点数量,然后读取、存储和处理其他顶点。

为了测试和演示目的,该表单还包含一个标记为“加载顶点”的按钮,单击该按钮时将执行名为 loadVertices() 的 JavaScript 函数。该函数读取请求的顶点数量,为表示内接于单位圆的多边形的顶点序列计算 x 和 y 坐标,并将这些值加载到表单中。增加顶点数量并重新计算内接多边形的面积和周长将演示生成内接多边形面积和周长的数值,这些数值会趋近于单位圆的值。

<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">

    // Two coordinate arrays
    var x = new Array();
    var y = new Array();
    var vertices;
    var digits;
    var area;
    var perimeter;
    
    function readUserData()
    {
        // Read the number of vertices
        vertices = parseInt( document.getElementById("VERTICES").value );
        if( (vertices < 3) || (vertices > 10 ) ) {
            alert( "Vertices must be >= 3 and <= 10" );
            return;
        }

        // Read the value of displayed digits
        digits = parseInt( document.getElementById("DIGITS").value );
        if( digits < 0 ) {
            alert( "Digits must be > 0" );
            return;
        }

        // Read and store the vertex x and y values
        for( k = 0; k < vertices; k++ ) {
            x[k] = parseFloat( document.getElementById("X"+k).value );
            y[k] = parseFloat( document.getElementById("Y"+k).value );
        }
        
        // Copy the values x[0] and y[0]
        // to the values x[vertices] and y[vertices]
        // to simplfy the area and perimeter calculations
        x[vertices] = x[0];
        y[vertices] = y[0];
    }

    function calculateArea()
    {
        // Calculate the area of a polygon
        // using the data stored
        // in the arrays x and y
        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()
    {
        // Calculate the perimeter
        // of a polygon using the data stored
        // in the arrays x and y
        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(); 
    
        // Display the x and y values using
        // the specified number of decimal digits
        displayCoordinates();
    
        // Display the calculated results
        document.getElementById("AREA").value = 
                          area.toFixed(digits);
        document.getElementById("PERIMETER").value = 
                          perimeter.toFixed(digits);
    }

    function loadVertices()
    {
        // Clear the form data, if any
        for( k = 0; k < 10; k++ ) {
            document.getElementById("X"+k).value = "";
            document.getElementById("Y"+k).value = "";
        }
        document.getElementById("AREA").value = "";
        document.getElementById("PERIMETER").value = ""; 
    
        // Read the number of vertices
        vertices = parseInt( document.getElementById("VERTICES").value ); 
        if( (vertices < 3) || (vertices > 10 ) ) {
            alert( "Vertices must be >= 3 and <= 10" );
            return;
        }
    
        // Read the value of displayed digits
        digits = parseInt(document.getElementById("DIGITS").value );
        if( digits < 0 ) {
            alert( "Digits must be > 0" );
            return;
        }

        // Assign and display each vertex's x and y values
        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&nbsp; </td>
<td colspan="2"><input type="text" 
         id="PERIMETER" size="20"></td>
<td>&nbsp;</td>
</tr>
<tr>
<td align="right">Area </td>
<td colspan="2"><input type="text" 
         id="AREA" size="20"></td>
<td>&nbsp;</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>

一个示例问题

Surveyor's formula 提供了一种简单、高效且统一的方法来计算任何多边形的面积。它是计算任何多边形面积的一个经常被忽视的替代技术。使用上面的 HTML 文档,可以轻松找到这个多边形的面积和周长。

表 1 包含一组具有 10 个顶点的不规则多边形样本数据。多边形的形状如图 1 所示。通过将多边形分解为更简单、更熟悉的形状,不容易获得这个相对简单的多边形的面积。

使用上面列出的 HTML 文档,可以轻松找到该多边形的面积为 3.188,周长为 7.772。

表 1:不规则多边形的坐标

x

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

图 1:不规则多边形

历史

  • 03-16-2006:
    • 原始文章。
Surveyor's Formula 的 JavaScript 实现 - CodeProject - 代码之家
© . All rights reserved.