標籤:計算幾何 球面
題目連結:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3598
題目大意:給出一個球體上的三點,三點的座標以經緯度的形式給出,求曲面三角形的內角和。
即:給出ABC三個點的經緯度,求出 角A+ 角B+角C的值。
利用公式即可求得 cosa=cosb*cosc+sinb*sinc*cosA
其中小寫a,b,c表示球面三角形邊長所對應的圓心角 大寫A表示三角形內角。
下面的難度就是求出abc角的大小即可。
網上看了一個寫法看了好久看不太懂:T.T
<span style="font-size:14px;">//計算圓心角lat表示緯度,-90<=w<=90,lng表示經度//返回兩點所在大圓劣弧對應圓心角,0<=angle<=pidouble angle(double lng1, double lat1, double lng2, double lat2){ double dlng = fabs(lng1 - lng2) * Pi / 180; while (dlng + eps > Pi + Pi) dlng -= Pi + Pi; if (dlng > Pi) dlng = Pi + Pi - dlng; lat1 *= Pi / 180, lat2 *= Pi / 180; return acos(cos(lat1) * cos(lat2) * cos(dlng) + sin(lat1) * sin(lat2));}</span>太水了,後來找到了一個能接受的寫法:
我們先把經緯度換為xyz座標。(預設了R是1)
比如已知一點A的座標為(x1,y1,z1),B的座標是(x2,y2,z2)
下面就是求角度AOB,向量OA為(x1,y1,z1),向量OB為(x2,y2,z2)。
OA*OB=|OA|*|OB|*cos(角AOB)=x1*x2+y1*y2+z1*z2
則就可以求出角AOB了。
具體演算法看代碼:
#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>const double PI = 2.0 * asin(1.0);using namespace std;struct po{ double x,y,z;};void m_change(double ll, double la, po& p){ p.x = cos(la * PI / 180) * cos(ll * PI / 180); p.y = cos(la * PI / 180) * sin(ll * PI / 180); p.z = sin(la * PI / 180);}double xlj(po p, po q){ return (p.x * q.x) + (p.y * q.y) + (p.z * q.z);}int main(){ int n; cin>>n; while(n--) { po A,B,C; cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y; m_change(A.x,A.y,A); m_change(B.x,B.y,B); m_change(C.x,C.y,C); double a = acos(xlj(C,B)); double b = acos(xlj(A,C)); double c = acos(xlj(A,B));// printf("a:%lf b:%lf c:%lf\n",a,b,c); double da,db,dc; da = acos((cos(a) - cos(b) * cos(c)) / (sin(b) * sin(c))); db = acos((cos(b) - cos(c) * cos(a)) / (sin(c) * sin(a))); dc = acos((cos(c) - cos(a) * cos(b)) / (sin(a) * sin(b)));// printf("da:%lf db:%lf dc:%lf\n",da,db,dc); double ans = da + db + dc; printf("%.2lf\n",ans * (180 / PI)); }}
Zoj 3598 Spherical Triangle 【計算幾何】【曲面三角形】