1. 程式人生 > >求任意多邊形面積與重心的演算法

求任意多邊形面積與重心的演算法



多邊形重心問題

時間限制:3000 ms  |  記憶體限制:65535 KB

難度:5

描述在某個多邊形上,取n個點,這n個點順序給出,按照給出順序將相鄰的點用直線連線, (第一個和最後一個連線),所有線段不和其他線段相交,但是可以重合,可得到一個多邊形或一條線段或一個多邊形和一個線段的連線後的圖形;
如果是一條線段,我們定義面積為0,重心座標為(0,0).現在求給出的點集組成的圖形的面積和重心橫縱座標的和;
輸入第一行有一個整數0<n<11,表示有n組資料;
每組資料第一行有一個整數m<10000,表示有這個多邊形有m個頂點;輸出輸出每個多邊形的面積、重心橫縱座標的和,小數點後保留三位;樣例輸入3
3
0 1
0 2
0 3
3
1 1
0 0
0 1
4
1 1
0 0
0 0.5
0 1
樣例輸出0.000 0.000
0.500 1.000
0.500 1.000

//給出一個程式

#include<stdio.h> double abs(double x){ if(x<0) return -x; else return x; } int main(){ int n,m; int i; double x0,y0,x1,y1,x2,y2; double s,si,sx,sy; scanf("%d",&n); while(n--){ s = 0; sx = 0; sy = 0; scanf("%d",&m); scanf("%lf %lf",&x0,&y0); scanf("%lf %lf",&x1,&y1); m -= 2; for(i=0;i<m;i++){ scanf("%lf %lf",&x2,&y2); si = ((x1-x0)*(y2-y0)-(x2-x0)*(y1-y0))/2; s += si; sx += (x0+x1+x2)*si/3; sy += (y0+y1+y2)*si/3; x1=x2; y1=y2; } s = abs(s); printf("%.3lf ",s); if(s==0) printf("0.000\n"); else printf("%.3lf\n",abs(sx+sy)/s); } return 0; }


原理
1.三角形重心公式
     ym=(y1+y2+y3)/3
證明:
設三點為A(x1.y1)B(x2,y2)C(x3,y3)
重心座標(xm,ym)
考慮xm
任取兩點(不妨設為A和B),則重心在以AB為底的中線上.
AB中點橫座標為(x1+x2)/2
重心在中線距AB中點1/3處
故重心橫座標為
xm=1/3*(x3-(x1+x2)/2)+(x1+x2)/2
=(x1+x2+x3)/3
同理,ym=(y1+y2+y3)/3
來源:https://www.zybang.com/question/ca313a8ed35fca221061c144089c70b1.html

2.三角形面積
    用向量叉乘運算
S=AB叉乘AC/2
正負由給出座標是順時針還是逆時針決定
座標式((x1-x0)*(y2-y0)-(x2-x0)*(y1-y0))/2

3.不規則多邊形面積,可以把他分成若干個小三角形,依次求和


當多邊形為凸多邊形,顯然成立


當多邊形為凹多邊形,則多邊形點給出的順序,一定會相反(有的是順時針,有的是逆時針),用該公式求出的面積為負,正好抵消,由此可知該方法對所有多邊形都成立