计算多边形面积

Calculating Polygon Area

本文关键字:多边形 计算      更新时间:2023-09-26

所以我已经得到这个代码在javascript计算不规则多边形面积从网络。

function polygonArea(X, Y, numPoints)  
{    
area = 0;  // Accumulates area in the loop   
j = numPoints-1;  // The last vertex is the 'previous' one to the first
  for (i=0; i<numPoints; i++)
  { area = area +  (X[j]+X[i]) * (Y[j]-Y[i]); 
      j = i;  //j is previous vertex to i
  }   
  return area/2; 
}
var xPts = [3, 3, 2, 2, 3, 3, 6, 6, 9, 9, 4, 4 ];
var yPts = [2, 4, 4, 5, 5, 6, 6, 5, 5, 3, 3, 2];
var a = polygonArea(xPts, yPts, 4); 
alert("Area  = " + a);

结果似乎是正确的。如果沿顺时针方向描顶点,它会显示正的结果然而如果沿逆时针方向描顶点,它会变成负的。为什么会这样呢?

这个算法是如何工作的?我真的很想知道它背后的数学解释是什么,因为我仍然很难理解网上的解释

有一个计算多边形面积的算法:

function calcPolygonArea(vertices) {
    var total = 0;
    for (var i = 0, l = vertices.length; i < l; i++) {
      var addX = vertices[i].x;
      var addY = vertices[i == vertices.length - 1 ? 0 : i + 1].y;
      var subX = vertices[i == vertices.length - 1 ? 0 : i + 1].x;
      var subY = vertices[i].y;
      total += (addX * addY * 0.5);
      total -= (subX * subY * 0.5);
    }
    return Math.abs(total);
}

想象从每个顶点到Y轴绘制水平线;对于每条边,这将描述一个梯形:

Y-axis
^
|
|--------o (X[j], Y[j])
|         '
|          '
|           '
|------------o (X[i], Y[i])
|
+----------------------------> X-axis

公式(X[j]+X[i]) * (Y[j]-Y[i])在内环计算两倍于Y[i] <= Y[j]的梯形面积,或者两倍于Y[i] >= Y[j]的面积。

对于一个封闭多边形,这很自然地将"上升"边左侧的面积从"下降"边左侧的面积中减去。如果多边形是顺时针的,这将整齐地切割出多边形的确切(加倍)面积;如果逆时针,则得到负(加倍)面积。

要计算给定多边形的面积,

Y-axis
^
|
|        o------o
|        |       '
|        |        '
|        o         '
|         '         o                  
|          '       /
|           '     /
|            '   /
|             ' /
|              o
|
+-------------------------> X-axis

取下行区:

Y-axis
^
|
|--------o------o
|                '
|                 '
|        o         '
|                   o                  
|                  /
|                 /
|                /
|               /
|--------------o
|
+-------------------------> X-axis

减去上升区域:

Y-axis
^
|
|--------o      o
|        |
|        |
|        o
|         '         o                  
|          '
|           '
|            '
|             '
|--------------o
|
+-------------------------> X-axis

虽然上面的例子使用了一个凸多边形,但是这个面积计算对于任意多边形都是正确的,不管它们可能有多少条上行和下行路径

下面是使用Andrii Verbytskyi的响应的代码片段:

/* Get area of a polygon/surface */
function area(polygon) {
    let total = 0;
    for (let i = 0; i < polygon.length; i++) {
        const addX = polygon[i][0];
        const addY = polygon[i === polygon.length - 1 ? 0 : i + 1][1];
        const subX = polygon[i === polygon.length - 1 ? 0 : i + 1][0];
        const subY = polygon[i][1];
        total += (addX * addY * 0.5) - (subX * subY * 0.5);
    }
    return Math.abs(total);
}
function drawPolygon(context, polygon, strokeStyle, fillStyle) {
  context.strokeStyle = strokeStyle;
  context.fillStyle = fillStyle;
  context.beginPath();
  context.moveTo(polygon[0][0], polygon[0][1]); //first vertex
  for (var i = 1; i < polygon.length; i++)
    context.lineTo(polygon[i][0], polygon[i][1]);
  context.lineTo(polygon[0][0], polygon[0][1]); //back to start
  context.fill();
  context.stroke();
  context.closePath();
}
display = function(n) {
  var context = document.getElementById("canvas").getContext("2d");
  context.clearRect(0, 0, 500, 500);
  drawPolygon(context, polygons[n], "#888", "#88f");
  document.querySelector('span').textContent = area(polygons[n]);
};
const polygons = [
    [[100, 100], [100, 300], [300, 400], [400, 250], [300, 0]],
    [[300, 300], [300, 100], [0, 0], [-100, 400]],
    [[50, 150], [200, 50], [350, 150], [350, 250], [250, 320], [200, 250], [150, 350], [100, 250]],
    [[100, 100], [300, 100], [400, 300], [100, 300]]
];
const buttons = document.querySelectorAll("button");
for (let counter = 0; counter < buttons.length; counter++) {
    buttons[counter].addEventListener("click", function(){
      window.onload = display(counter);
   });
}
window.onload = display(0);
<button onclick="display(0)">Polygon 0</button>
<button onclick="display(1)">Polygon 1</button>
<button onclick="display(2)">Polygon 2</button>
<button onclick="display(3)">Polygon 3</button>
Polygon area : <span id='area'></span>
<canvas id='canvas' width='400' height='400'></canvas>

这背后没有魔法。看看矩阵的行列式(http://en.wikipedia.org/wiki/Determinant#2.C2.A0.C3.97.C2.A02_matrices)

编辑:

老实说:这段代码中有一些魔法:

  1. 你需要任何三角测量。这里:我们从(0,0)开始创建三角形,(Xi, Yi)(Xj, Yj)
  2. 你计算每个三角形的行列式得到:Xi Yj - Xj Yi。但这里有人计算(X[j]+X[i]) * (Y[j]-Y[i]) = Xj Yj - Xj Yi + Xi Yj - Xi Yi = (Xj Yj - Xi Yi) + (Xi Yj - Xj Yi)。但如果你把这些都加起来,(Xj Yj - Xi Yi)就消掉了。所以这是一个棘手的部分。

累计每个定向段p [i], p [i+1]与Y轴之间的带符号区域。在循环结束时,多边形外部的区域被消去(它将以不同的符号计数两次),而内部的带符号区域保留。