Üçgenin küresel fazlalığı


15

Üçgenin küresel fazlalığı

Hepimizin bildiği gibi, herhangi bir düzlemsel üçgenin açılarının toplamı 180 dereceye eşittir.

Bununla birlikte, küresel üçgenin için, açıların toplamı her zaman daha 180 derece. Küresel üçgen açıların toplamı ile 180 derece arasındaki farka küresel fazlalık denir . Görev, bir üçgenin küresel fazlalığını verilen tepe koordinatları ile hesaplamaktır.

Bazı arka plan

Küresel bir üçgen, kürenin üç büyük dairesi tarafından tanımlanan kürenin bir parçasıdır.

Küresel üçgenin her iki tarafı ve açıları, açı ölçüsü açısından ölçülür, çünkü her bir taraf kürenin kesişimi ve kürenin ortasındaki tepe noktası olan bazı düzlemsel bir açı olarak düşünülebilir:

Küresel üçgen açıklandı

Her üç ayrı büyük daire 8 üçgen tanımlar, ancak yalnızca uygun üçgenleri dikkate alırız , yani. açısı ve yan ölçüleri tatmin eden üçgenler

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

Bir üçgenin köşelerini coğrafi koordinat sistemi olarak tanımlamak uygundur. Uçlarının λ boylamı ve enlemi given verilen bir kürenin uzunluğunu hesaplamak için aşağıdaki formülü kullanabiliriz:

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

, nerede

\ Operatorname {Haversin} (\ teta) = \ sin ^ 2 \ sol (\ frac {\ teta} {2} \ sağ) = \ frac {1- \ cos (\ teta)} {2}

veya daha açık bir şekilde:

d = 2 r \ arcsin \ left (\ sqrt {\ sin ^ 2 \ left (\ frac {\ phi_2 - \ phi_1} {2} \ sağ) + \ cos (\ phi_1) \ cos (\ phi_2) \ sin ^ 2 \ sol (\ frac {\ lambda_2 - \ lambda_1} {2} \ right)} \ right)

(kaynak: https://en.wikipedia.org/wiki/Haversine_formula )

Küresel bir üçgeni çözmek için kullanılabilecek iki temel formül şunlardır:

  • kosinüs yasası:

\ 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

  • sinüs yasası:

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

(kaynak: https://en.wikipedia.org/wiki/Spherical_trigonometry#Cosine_rules_and_sine_rules )

Üç taraf verildiğinde, kosinüs kuralını kullanarak açıları hesaplamak kolaydır:

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}

Son olarak, bir üçgenin küresel fazlalığı tanımlanır:

E = A + B + C - \ pi

Bir üçgenin küresel fazlalığı ve alanı arasındaki ilişki hakkında ilginç olan şey:

S = E \ cdot R ^ 2

Yani bir birim kürede, bir üçgenin fazlası o üçgenin alanına eşittir!

Görev

Üçgen köşeleri koordinatları verildiğinde, bir üçgenin küresel fazlalığını derece cinsinden hesaplayacak bir işlev veya program yazın. Tepe koordinatları, coğrafi koordinat sistemi olarak sağlanır.

Her tepe noktası formda geçirilmelidir [latitude in degrees][N|S][longitude in degrees][E|W]. Boylam ve / Eveya Wenlem 90 olduğunda atlanabilir . 90N, 90S, 10N100E, 30S20WAncak uygun köşe açıklamalarıdır 80Nveya 55Sdeğildirler.

Test durumlarında enlemler ve boylamlar her zaman tamsayıdır.

Bir dereceden az hatalı cevaplar kabul edilecektir (aşağıdaki örneklerde olduğu gibi). Sonuç, size kolaylık sağlamak için hem gerçek hem de tamsayı olarak elde edilebilir.

Örnekler

Giriş

90N0E
0N0E
0N90E

Çıktı

89.999989

Giriş

90N
0N0E
0N90E

Çıktı

89.999989

Giriş

0N0E
0N179E
90N0E

Çıktı

178.998863

Giriş

10N10E
70N20W  
70N40E

Çıktı

11.969793

Tüm test durumlarında boylam ve enlem tam sayıdır. Bir köşe tek dize / literal olarak geçmiş olması gerekir, böylece köşe koordinatları Ayrıştırma, görevinin bir parçasıdır, bu geçmesine izin vermiyor 80N20Edört parametre / dizeleri olarak: 80, N, 20, E.

Bu, köşelerin hepsinin farklı olduğu ve üç köşeden hiçbirinin bir antipodal nokta çifti oluşturmadığı garanti edilir.

puanlama

Bu , bu yüzden en kısa kod kazanır.


1
İlk birkaç test durumu için doğru çıktılar 90 derece ve 179 derecedir. Anlamak zorunda olduklarını söylüyorum, ama kaç ondalık doğruluk yeri gerekli?
Level River St

@steveverrill Görev güncellendi. Bir derecelik doğruluk yeterlidir.
pawel.boczarski

@ pawel.boczarski Enlemler / boylamlar her zaman tamsayı mıdır?
flawr

@flawr Evet, görevi güncelledim.
pawel.boczarski

Yanıtlar:


4

Matlab, 288 bayt

Neler olup bittiğini açıklaması gereken yorumlanmış sürüm:

                                  %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)

Tamamen golf oynamak (çizgi vuruşları kaldırılabilir):

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 264255 bayt

Büyük değişiklikler:

Yeni sabit r= 180 / PI işlev boyunca tanımlanmış ve kullanılmıştır. e+ PI olarak başlatılmalıydı, bu yüzden fazlalık aşağı doğru sayar ve geri dönmeden önce reddedilir.

t[]elendi: Ruby, atanan verilerin t[]doğrudan atanmasına izin veriru,v,w.

iİki döngü işini yapmak için tek döngü, ?:üçlü operatör görevler arasında geçiş yapar.

Diğer birçok küçük değişiklik.

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}

Yakut Rev 1 283 277 bayt

3 dize dizisi gerektirir.

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}

genel bakış

Birim küredeki üçgen kenarların uzunlukları, iki noktayı tanımlayan vektörler arasındaki açılara eşittir. Ama bu açıyı bilmemize gerek yok. Nokta Ürünü kullanılarak kartezyen koordinatlardan kolayca elde edilebilen açının kosinüsünü bilmek yeterlidir.

açıklama

Giriş dizeleri, bir dizinin dize olarak temsil edilmesine dönüştürülür ve daha sonra taşağıdaki gibi değerlendirilir ve depolanır . İki koordinat verilirse son sıfır gerekmez. Sadece enlem 90 verilirse, sıfır boylam olarak yorumlanır.

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

Dot Ürünleri biçimindedir a.b=ax*bx+ay*by+az*bz. Vektörlerin tamamı birim uzunluk olduğundan, nokta ürün vektörler arasındaki açının kosinüsüne eşittir.

Bunları hesaplamak için bir döngü, giriş verilerinden iki kez geçerek 6 kez tekrarlanır. Hatta 0,2,4 yinelemelerinde, değişkenler x,y,zyeni bir hesaplamaya başlamak için 1'e ayarlanır. Her bir yinelemede bu değişkenler, saklanan boylam ve enlem verileri kullanılarak t[0],t[1](golf nedenleriyle de atanır u,v) her vektörün x, y ve z bileşenleri ile çarpılır . Değişkenlerin toplamı diziye yazılır n(tek yinelemelerdeki çöp değerlerinin üzerine tek değer yinelemelerde doğru değerlerin üzerine yazılır), böylece sonunda n3 nokta ürünü bulunur [a.b, c.a, b.c].

Kosinüs kuralı için, köşeler arasındaki üç açının kosinüslerine ihtiyacımız var, ama aynı zamanda sinüslere de ihtiyacımız var. Bunlar olarak elde edilir sqrt(1-cosine**2). Sinüsler birlikte çoğaldıkça, ifade sadece bir çağrı gerekecek şekilde yeniden düzenlenebilir sqrt. Haversin formülü her zaman pozitif sinüsü verir, çünkü sinüsün pozitif mi negatif mi olduğunu bilmiyoruz. Önemli fiziksel miktar, noktalar arasındaki mesafedir, ki bu mutlak ve bu nedenle daima pozitiftir.

Her bir yineleme i=0..2için i-1, diğer elemanları ive kullanarak, karşıt dizi elemanının açısının değerini hesaplar i-2. Bunun gibi negatif dizi abonelikleri Ruby'de yasaldır, sadece dizinin başına sarılırlar.

Test programında yönlendirilmemiş

Aynı satırda, aralarında boşluk bulunan üç koordinat seti gerektirir.

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]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.