Вычисление области неправильного полигона в C#

Мне удалось записать 'для макетов', как вычислить область неправильного полигона в C#, но мне нужен он, чтобы быть динамичным для любой суммы verticies.

Кто-то может помочь?

Класс:

public class Vertex
{
    private int _vertexIdx;
    private double _coordX;
    private double _coordY;
    private double _coordZ;

    public Vertex()
    { }

    public Vertex(int vertexIdx, double coordX, double coordY, double coordZ)
    {
        _vertexIdx = vertexIdx;
        _coordX = coordX;
        _coordY = coordY;
        _coordZ = coordZ;
    }

    public int VertexIdx
    {
        get { return _vertexIdx; }
        set { _vertexIdx = value; }
    }

    public double X
    {
        get { return _coordX; }
        set { _coordX = value; }
    }

    public double Y
    {
        get { return _coordY; }
        set { _coordY = value; }
    }

    public double Z
    {
        get { return _coordZ; }
        set { _coordZ = value; }
    }
}

Form_Load:

List<Vertex> verticies = new List<Vertex>();

verticies.Add(new Vertex(1, 930.9729, 802.8789, 0));
verticies.Add(new Vertex(2, 941.5341, 805.662, 0));
verticies.Add(new Vertex(3, 946.5828, 799.271, 0));
verticies.Add(new Vertex(4, 932.6215, 797.0548, 0));

dataGridView1.DataSource = verticies;

Код для вычисления, когда кнопка нажимается: (трудно кодированный для 4 полигонов точек - должен быть для любой суммы...),

        // X-coords
        double x1;
        double x2;
        double x3;
        double x4;
        double x5;

        // Y-coords
        double y1;
        double y2;
        double y3;
        double y4;
        double y5;

        // Xn * Yn++
        double x1y2;
        double x2y3;
        double x3y4;
        double x4y5;

        // Yn * Xn++
        double y1x2;
        double y2x3;
        double y3x4;
        double y4x5;

        // XnYn++ - YnXn++
        double x1y2my1x2;
        double x2y3my2x3;
        double x3y4my3x4;
        double x4y5my4x5;

        double result;
        double area;

        x1 = Convert.ToDouble(dataGridView1.Rows[0].Cells[1].Value.ToString());
        y1 = Convert.ToDouble(dataGridView1.Rows[0].Cells[2].Value.ToString());
        txtLog.Text += String.Format("X1 = {0}\tY1 = {1}\r\n", x1, y1);

        x2 = Convert.ToDouble(dataGridView1.Rows[1].Cells[1].Value.ToString());
        y2 = Convert.ToDouble(dataGridView1.Rows[1].Cells[2].Value.ToString());
        txtLog.Text += String.Format("X2 = {0}\tY2 = {1}\r\n", x2, y2);

        x3 = Convert.ToDouble(dataGridView1.Rows[2].Cells[1].Value.ToString());
        y3 = Convert.ToDouble(dataGridView1.Rows[2].Cells[2].Value.ToString());
        txtLog.Text += String.Format("X3 = {0}\tY3 = {1}\r\n", x3, y3);

        x4 = Convert.ToDouble(dataGridView1.Rows[3].Cells[1].Value.ToString());
        y4 = Convert.ToDouble(dataGridView1.Rows[3].Cells[2].Value.ToString());
        txtLog.Text += String.Format("X4 = {0}\tY4 = {1}\r\n", x4, y4);

        // add the start point again
        x5 = Convert.ToDouble(dataGridView1.Rows[0].Cells[1].Value.ToString());
        y5 = Convert.ToDouble(dataGridView1.Rows[0].Cells[2].Value.ToString());
        txtLog.Text += String.Format("X5 = {0}\tY5 = {1}\r\n", x5, y5);
        txtLog.Text += "\r\n";

        // Multiply 
        x1y2 = x1 * y2;
        x2y3 = x2 * y3;
        x3y4 = x3 * y4;
        x4y5 = x4 * y5;

        y1x2 = y1 * x2;
        y2x3 = y2 * x3;
        y3x4 = y3 * x4;
        y4x5 = y4 * x5;

        // Subtract from each other
        x1y2my1x2 = x1y2 - y1x2;
        x2y3my2x3 = x2y3 - y2x3; 
        x3y4my3x4 = x3y4 - y3x4;
        x4y5my4x5 = x4y5 - y4x5;

        // Sum all results
        result = x1y2my1x2 + x2y3my2x3 + x3y4my3x4 + x4y5my4x5;
        area = Math.Abs(result / 2);

        txtLog.Text += String.Format("Area = {0}\r\n", area);

Пример произвел:

X1 = 930.9729 Y1 = 802.8789

X2 = 941.5341 Y2 = 805.662

X3 = 946.5828 Y3 = 799.271

X4 = 932.6215 Y4 = 797.0548

X5 = 930.9729 Y5 = 802.8789

Область = 83.2566504099523

10
задан riaandl 9 January 2010 в 19:02
поделиться

2 ответа

Что-то вроде этого для простого многоугольника (скомпилировано в блокноте):

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

Хотя ваш подход не обращает внимания на ось Z. Поэтому я бы посоветовал применить некоторую трансформацию, чтобы избавиться от него: вы не сможете получить площадь, если многоугольник не плоский, тогда как если это плоскость, вы можете избавиться от третьего измерения.

3
ответ дан 3 December 2019 в 16:52
поделиться
        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();
0
ответ дан 3 December 2019 в 16:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: