2010-01-09 12 views
5

C#, 'daki düzensiz poligon alanını nasıl hesaplayacağımı bir' mankenler için 'yazmayı başarabildim ama herhangi bir köşe noktası için dinamik olması gerekiyor.C Düzensiz Çokgen Alanının Hesaplanması C#

Birisi yardım edebilir mi?

Sınıf:

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: (4 puan çokgen için kodlanmış - herhangi bir miktar için olması gerekir: düğmesine basıldığında hesaplamak için

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;

kod. ..)

 // 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); 

Örnek çıktı:

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

Alan = (not defteri tarafından derlenen) bir plain polygon için böyle 83,2566504099523

+0

Ekran görüntüsü Microstation calculator = http://img15.imageshack.us/img15/6523/areaofpolygon.png – riaandelange

+0

Daha önce gördüğüm tipik bir yöntem çokgeni üçgenlere ayırmaktır, o zaman alanı kolayca toplayabilirsin tüm üçgenlerin. Bu, çokgenlerin karmaşıklığına (çapraz kenarlar, delikler, dışbükey/içbükey, vb.) Bağlı olarak farklı algoritmalara ihtiyaç duyduğundan öte bir şey değildir. –

+0

Bu soruyu http://mathoverflow.net/, bir Yığın Taşması site gibi, sadece matematik soruları için, sadece programlama olmayan bir soru olarak sorduğunuzdan emin olun ve bunun yerine algoritmik yaklaşımı isteyin. –

cevap

10

lambda ifadeleri kullanma bu önemsiz hale gelir! Algoritma here açıklanmıştır.

+0

Bağlantılı "açıklama", * algoritmayı açıklamamaktadır. Sadece kodu farklı şekilde sunar. –

3

şey:

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

rağmen Z eksenine dikkat gelmez yaklaşım. Bu yüzden, ondan kurtulmak için bazı dönüşümleri uygulamanızı tavsiye ederim: eğer çokgen düzlem değilse, alan elde edemeyeceksiniz, oysa düzlemse üçüncü boyuttan kurtulabilirsiniz.

+0

Yani, 2D ve 3D olarak hesaplanan alan arasında bir fark var mı? – riaandelange

+0

Evet, birazcık. Alan SADECE düz nesneler için hesaplanabilir. Bu nedenle poligonunuz düz olmalıdır - tüm köşeleri aynı düzlükte uzanmalıdır, aksi halde alan hesaplanamaz. Sorun, bu düzlemin her zaman örneğinizde olduğu gibi Z = 0 düzlemi olmamasıdır. Bunu hesaba katmadan önce dikkate almalı ve noktaları uygun şekilde işlemelisiniz. – Li0liQ

0
 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(); 
4
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); 
} 
+1

Lütfen cevabınızın kolay anlaşılması için bazı açıklamalarda bulunun. – Carsten