Hình cầu thừa của một hình tam giác


15

Hình cầu thừa của một hình tam giác

Như chúng ta đã biết, tổng các góc của bất kỳ tam giác phẳng nào đều bằng 180 độ.

Tuy nhiên, đối với một hình tam giác hình cầu, tổng các góc luôn lớn hơn 180 độ. Sự khác biệt giữa tổng các góc tam giác hình cầu và 180 độ được gọi là thừa hình cầu . Nhiệm vụ là tính toán thừa hình cầu của một tam giác với tọa độ đỉnh đã cho.

Một số nền tảng

Một hình tam giác hình cầu là một phần của hình cầu được xác định bởi ba vòng tròn lớn của hình cầu.

Cả hai cạnh và góc của tam giác hình cầu đều được đo theo thuật ngữ đo góc, bởi vì mỗi bên có thể được coi là một giao điểm của hình cầu và một số góc phẳng với đỉnh ở tâm của hình cầu:

Tam giác hình cầu giải thích

Mỗi ba vòng tròn lớn riêng biệt xác định 8 hình tam giác, nhưng chúng tôi chỉ mất tam giác thích hợp vào xem xét, tức là. tam giác có các số đo góc và cạnh thỏa mãn

0 <a, b, c, A, B, C <\ pi

Thật thuận tiện khi xác định các đỉnh của một tam giác theo hệ tọa độ địa lý. Để tính độ dài của một cung tròn hình cầu cho kinh độ và vĩ độ Φ của các đầu của nó, chúng ta có thể sử dụng công thức:

d = 2 r \ arcsin \ left (\ sqrt {\ operatorname {haversin} (\ phi_2 - \ phi_1) + \ cos (\ phi_1) \ cos (\ phi_2) \ operatorname {haversin} (\ lambda_2- \ lambda_1)} \đúng)

, Ở đâu

\ operatorname {haversin} (\ theta) = \ sin ^ 2 \ left (\ frac {\ theta} {2} \ right) = \ frac {1- \ cos (\ theta)} {2}

hoặc rõ ràng hơn:

d = 2 r \ arcsin \ left (\ sqrt {\ sin ^ 2 \ left (\ frac {\ phi_2 - \ phi_1} {2} \ phải) + \ cos (\ phi_1) \ cos (\ phi_2) \ sin ^ 2 \ trái (\ frac {\ lambda_2 - \ lambda_1} {2} \ phải)} \ phải)

(nguồn: https://en.wikipedia.org/wiki/Haversine_formula )

Hai công thức cơ bản có thể được sử dụng để giải tam giác hình cầu là:

  • định luật vũ trụ:

\ cos a = \ cos b \ cos c + \ sin b \ sin c \ cos A, \ cos b = \ cos c \ cos a + \ sin c \ sin a \ cos B, \ cos c = \ cos a \ cos b + \ sin a \ sin b \ cos C

  • luật của tội lỗi:

\ frac {\ sin A} {\ sin a} = \ frac {\ sin B} {\ sin b} = \ frac {\ sin C} {\ sin c}

(nguồn: https://en.wikipedia.org/wiki/Spherical_trigonometry#Cosine_rules_and_sine_rules )

Có ba mặt, thật dễ dàng để tính toán các góc bằng quy tắc cosin:

A = \ arccos \ frac {\ cos a - \ cos b \ cos c} {\ sin b \ sin c}, B = \ arccos \ frac {\ cos b - \ cos c \ cos a} {\ sin c \ sin a}, C = \ arccos \ frac {\ cos c - \ cos a \ cos b} {\ sin a \ sin b}

Cuối cùng, phần thừa của hình tam giác được xác định:

E = A + B + C - \ pi

Điều thú vị về mối quan hệ giữa sự dư thừa hình cầu của một hình tam giác và diện tích của nó:

S = E \ cdot R ^ 2

Vì vậy, trên một hình cầu đơn vị, phần thừa của một hình tam giác bằng diện tích của hình tam giác đó!

Nhiệm vụ

Viết hàm hoặc chương trình sẽ tính vượt quá hình cầu của một tam giác theo độ cho các tọa độ đỉnh tam giác. Các tọa độ đỉnh được cung cấp theo hệ thống tọa độ địa lý.

Mỗi đỉnh phải được thông qua dưới dạng [latitude in degrees][N|S][longitude in degrees][E|W]. Kinh độ và Ehoặc Wcó thể bỏ qua khi vĩ độ là 90 tức là. 90N, 90S, 10N100E, 30S20WLà những mô tả đỉnh thích hợp, trong khi 80Nhoặc 55Skhông.

Các vĩ độ và kinh độ luôn là số nguyên trong các trường hợp thử nghiệm.

Các câu trả lời có lỗi nhỏ hơn một độ sẽ được chấp nhận (như trong ví dụ dưới đây). Do đó, kết quả có thể được hiển thị là cả thực hoặc số nguyên, tùy theo sự thuận tiện của bạn.

Ví dụ

Đầu vào

90N0E
0N0E
0N90E

Đầu ra

89.999989

Đầu vào

90N
0N0E
0N90E

Đầu ra

89.999989

Đầu vào

0N0E
0N179E
90N0E

Đầu ra

178.998863

Đầu vào

10N10E
70N20W  
70N40E

Đầu ra

11.969793

Trong tất cả các trường hợp kiểm tra kinh độ và vĩ độ là số nguyên. Phân tích các tọa độ đỉnh là một phần của công việc, do đó, một đỉnh phải được thông qua như chuỗi đơn / đen, nó không được phép vượt qua 80N20Enhư bốn thông số / chuỗi: 80, N, 20, E.

Điều này được đảm bảo rằng các đỉnh đều khác biệt và cả hai đỉnh đều không tạo thành một cặp điểm đối cực.

Chấm điểm

Đây là , vì vậy đoạn mã ngắn nhất sẽ thắng.


1
Các đầu ra chính xác cho một vài trường hợp thử nghiệm đầu tiên là 90 độ và 179 độ. Tôi hiểu rằng bạn đang nói rằng họ không cần phải phát hiện ra, nhưng cần bao nhiêu vị trí chính xác thập phân?
Cấp sông St

@steveverrill Cập nhật nhiệm vụ. Độ chính xác của một độ là đủ.
pawel.boczarski

@ pawel.boczarski Các vĩ độ / kinh độ luôn là số nguyên?
flawr

@flawr Vâng, tôi đã cập nhật nhiệm vụ.
pawel.boczarski

Câu trả lời:


4

Matlab, 288 266 byte

Ở đây phiên bản nhận xét sẽ giải thích những gì đang xảy ra:

                                  %parsing the input
for k=1:3;
    s=input('','s');              %request input
    if sum(s>57)<2;               %if we have only one letter, add arbitrary second coordinate
        s=[s,'0E'];
    end;
    S=1-2*(s(s>57)>80);           %calculate the sign of the coordinates
    s(s>57)=44;                   %replace letters with comma
    L(k,:)=eval(['[',s,']']).*S;  %evaluates string as list and multiply with signs
end;
i=[2,3,1];
                                  %calculate the angular distance between each pair of points
a=arrayfun(@distance,L(:,1),L(:,2),L(i,1),L(i,2))*pi/180;
                                  %evaluate the spherical excess
f=@(a,b,c)sum(acos((cos(a)-cos(b).*cos(c))./(sin(b).*sin(c))))-pi;
disp(f(a,a(i),a([3,1,2]))*180/pi)

Chơi golf hoàn toàn (ngắt dòng có thể được gỡ bỏ):

for k=1:3;s=input('','s');if sum(s>57)<2;s=[s,'0E'];end;
s(s>57)=44;L(k,:)=eval([91,s,93]).*(1-2*(s(s<48)>80));end;
i=[2,3,1];p=pi/180;a=arrayfun(@distance,L(:,1),L(:,2),L(i,1),L(i,2))*p;
b=a(i);disp((sum(acos((cos(a([3,1,2]))-cos(b).*cos(a))./(sin(b).*sin(a))))-pi)/p)

3

Ruby, Rev 3 264 255 byte

Sự thay đổi chính:

Hằng số mới r= 180 / PI được xác định và sử dụng trong suốt chức năng. ephải được khởi tạo thành + PI, vì vậy số dư thừa sẽ giảm xuống và bị phủ định trước khi quay trở lại.

t[]bị loại bỏ: Ruby cho phép dữ liệu được chỉ định được gán t[]trực tiếpu,v,w.

iVòng lặp đơn để thực hiện công việc của hai,?: toán tử ternary chuyển đổi giữa các tác vụ.

Nhiều thay đổi nhỏ khác.

include Math
->s{r=180/e=PI
x=y=z=n=[]
9.times{|i|i<6?(u,v,w=eval(?[+s[i%3].gsub(/[NE]/,"/r,").gsub(/[SW]/,"/-r,")+"0]")
i%2<1&&x=y=z=1
n[i/2]=(z*=sin(u))+(y*=cos(v)*w=cos(u))+x*=w*sin(v)):e-=acos((n[i-7]-(c=n[i-6])*d=n[i-8])/sqrt((1-c*c)*(1-d*d)))}
-e*r}

Ruby, Rev 1 283 277 byte

Yêu cầu một mảng gồm 3 chuỗi.

include Math 
->s{x=y=z=n=[]
6.times{|i|t=eval(?[+s[i%3].gsub(/[NE]/,k="*PI/180,").gsub(/[SW]/,"*-1"+k)+"0]")
i%2<1&&x=y=z=1
n[i/2]=(z*=sin(u=t[0]))+(y*=cos(u)*cos(v=t[1]))+(x*=cos(u)*sin(v))}
e=-PI
3.times{|i|e+=acos((n[i-1]-n[i]*d=n[i-2])/sqrt((1-n[i]**2)*(1-d**2)))}
e/PI*180}

Tổng quat

Độ dài của các cạnh tam giác trên mặt cầu đơn vị bằng với các góc giữa các vectơ mô tả hai điểm. Nhưng chúng ta không cần phải biết góc độ đó. Nó đủ để biết cosin của góc, có thể dễ dàng thu được từ tọa độ cartesian bằng cách sử dụng Sản phẩm Dot.

Giải trình

Các chuỗi đầu vào được chuyển đổi thành một chuỗi đại diện của một mảng, sau đó được đánh giá và lưu trữ trong t, như dưới đây. Số không cuối cùng là không cần thiết nếu hai tọa độ được đưa ra. Nếu chỉ có vĩ độ 90 được đưa ra, số 0 được hiểu là kinh độ.

Example:  70N20W --> [70*PI/180,20*-1*PI/180,0]

Các sản phẩm Dot có dạng a.b=ax*bx+ay*by+az*bz . Vì các vectơ đều có độ dài đơn vị, nên sản phẩm chấm bằng cosin của góc giữa các vectơ.

Để tính toán chúng, một vòng lặp được lặp lại 6 lần đi qua hai lần thông qua dữ liệu đầu vào. Trên các lần lặp chẵn 0,2,4, các biến x,y,zđược đặt thành 1 để bắt đầu một phép tính mới. Trên mỗi lần lặp, các biến này được nhân với các thành phần x, y và z của mỗi vectơ, sử dụng dữ liệu kinh độ và vĩ độ được lưu trữ t[0],t[1](vì lý do chơi gôn cũng được gán cho u,v). Tổng các biến được ghi vào mảng n(các giá trị rác trên các lần lặp chẵn được ghi đè bằng các giá trị đúng trên các lần lặp lẻ) để ở cuối ncó chứa các sản phẩm 3 chấm [a.b, c.a, b.c].

Đối với quy tắc cosin, chúng ta cần cosin của ba góc bao gồm giữa các đỉnh, nhưng chúng ta cũng cần các sin. Chúng được lấy là sqrt(1-cosine**2). Khi các sin được nhân với nhau, biểu thức có thể được sắp xếp lại để chỉ cần một cuộc gọi đến sqrt. Thực tế là chúng ta không biết liệu sin là dương hay âm không quan trọng, vì công thức haversine luôn mang lại cho sin tích cực. Đại lượng vật lý quan trọng là khoảng cách giữa các điểm, là tuyệt đối và do đó luôn luôn dương.

Đối với mỗi lần lặp i=0..2, chúng tôi tính giá trị cho phần tử mảng đối diện góc i-1bằng các phần tử khác ii-2. Các đăng ký mảng âm như thế này là hợp pháp trong Ruby, chúng chỉ bao quanh đến đầu mảng.

Ungolfed trong chương trình thử nghiệm

Yêu cầu ba bộ tọa độ trên cùng một dòng, với khoảng cách giữa chúng.

include Math
g=->s{
  n=[]         #array for dot products
  x=y=z=1      #it's required to use these variables once before the loop, for some bizarre reason
  6.times{|i|
    t=eval(?[+s[i%3].gsub(/[NE]/,k="*PI/180,").gsub(/[SW]/,"*-1"+k)+"0]")
    i%2<1&&x=y=z=1
    n[i/2]=(z*=sin(u=t[0]))+(y*=cos(u)*cos(v=t[1]))+(x*=cos(u)*sin(v))
  }

  e=-PI        #set e to -PI and begin accumulating angles
  3.times{|i|
    e+=acos((n[i-1]-n[i]*n[i-2])/sqrt((1-n[i]**2)*(1-n[i-2]**2)))
  }

e/PI*180}      #return value

puts g[gets.split]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.