Calculating Area of Irregular Polygon in C#

感情迁移 提交于 2019-11-28 21:37:52
l33t

Using lambda expressions this becomes trivial!

var points = GetSomePoints();

points.Add(points[0]);
var area = Math.Abs(points.Take(points.Count - 1)
   .Select((p, i) => (points[i + 1].X - p.X) * (points[i + 1].Y + p.Y))
   .Sum() / 2);

The algorithm is explained here:

[This method adds] the areas of the trapezoids defined by the polygon's edges dropped to the X-axis. When the program considers a bottom edge of a polygon, the calculation gives a negative area so the space between the polygon and the axis is subtracted, leaving the polygon's area.

The total calculated area is negative if the polygon is oriented clockwise [so the] function simply returns the absolute value.

This method gives strange results for non-simple polygons (where edges cross).

public float Area(List<PointF> vertices)
{
    vertices.Add(vertices[0]);
    return Math.Abs(vertices.Take(vertices.Count - 1).Select((p, i) => (p.X * vertices[i + 1].Y) - (p.Y * vertices[i + 1].X)).Sum() / 2);
}

Something like that for a plain polygon (compiled by notepad):

static double GetDeterminant(double x1, double y1, double x2, double y2)
{
    return x1 * y2 - x2 * y1;
}

static double GetArea(IList<Vertex> vertices)
{
    if(vertices.Count < 3)
    {
        return 0;
    }
    double area = GetDeterminant(vertices[vertices.Count - 1].X, vertices[vertices.Count - 1].Y, vertices[0].X, vertices[0].Y);
    for (int i = 1; i < vertices.Count; i++)
    {
        area += GetDeterminant(vertices[i - 1].X, vertices[i - 1].Y, vertices[i].X, vertices[i].Y);
    }
    return area / 2;
}

Although your approach doesn't pay attention to Z-axis. Therefore I'd advice to apply some transformation to get rid of it: you won't be able to get area if the polygon is not plane, whereas if it is plane you are able to get rid of the third dimension.

        double resultant = 0;
        double area = 0;
        int tel1 = 0;
        int tel2 = 0;

        x1y2lst.Clear();
        y1x2lst.Clear();
        x1y2lstMinusy1x2lst.Clear();

        // *******************************************************************************************//
        // Calculate and populate X1 * Y2 in a list

        for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
        {
            tel1++;
            double x1x = Convert.ToDouble(dataGridView1.Rows[i].Cells[1].Value.ToString());
            double y2y = Convert.ToDouble(dataGridView1.Rows[i+1].Cells[2].Value.ToString());
            x1y2lst.Add(x1x * y2y);
        }
        // Calculate the last with the first value
        double xLastx = Convert.ToDouble(dataGridView1.Rows[tel1].Cells[1].Value.ToString());
        double yFirsty = Convert.ToDouble(dataGridView1.Rows[0].Cells[2].Value.ToString());
        x1y2lst.Add(xLastx * yFirsty);

        // *******************************************************************************************//
        // Calculate and populate Y1 * X2 in a list
        for (int i = 0; i < dataGridView1.Rows.Count - 1; i++)
        {
            tel2++;
            double y1y = Convert.ToDouble(dataGridView1.Rows[i].Cells[2].Value.ToString());
            double x2x = Convert.ToDouble(dataGridView1.Rows[i + 1].Cells[1].Value.ToString());
            y1x2lst.Add(y1y * x2x);
        }
        // Calculate the last with the first value
        double yLasty = Convert.ToDouble(dataGridView1.Rows[tel2].Cells[2].Value.ToString());
        double xFirstx = Convert.ToDouble(dataGridView1.Rows[0].Cells[1].Value.ToString());
        y1x2lst.Add(yLasty * xFirstx);

        // Subract List1 values from List2 values
        for (int k = 0; k < x1y2lst.Count; k++)
        {
            x1y2lstMinusy1x2lst.Add(x1y2lst[k] - y1x2lst[k]);
        }

        // Add all answers from previous to a result
        for (int l = 0; l < x1y2lstMinusy1x2lst.Count; l++)
        {
            resultant += x1y2lstMinusy1x2lst[l];
        }
        // Area = Result from steps above devided by 2
        area = Math.Abs(resultant / 2);
        txtArea.Text = Math.Round(area, 4).ToString();
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!