Eccesso sferico di un triangolo


15

Eccesso sferico di un triangolo

Come tutti sappiamo, la somma degli angoli di qualsiasi triangolo planare è pari a 180 gradi.

Tuttavia, per un triangolo sferico, la somma degli angoli è sempre maggiore di 180 gradi. La differenza tra la somma degli angoli triangolari sferici e 180 gradi è chiamata eccesso sferico . Il compito è calcolare l'eccesso sferico di un triangolo con le coordinate del vertice indicate.

Qualche sfondo

Un triangolo sferico è una parte della sfera definita da tre grandi cerchi della sfera.

Entrambi i lati e gli angoli del triangolo sferico sono misurati nel termine della misura angolare, poiché ogni lato può essere considerato come un'intersezione della sfera e un angolo planare con vertice al centro della sfera:

Spiegazione del triangolo sferico

Ogni tre grandi cerchi distinti definiscono 8 triangoli, ma prendiamo in considerazione solo i triangoli appropriati , vale a dire. triangoli le cui misure angolari e laterali soddisfano

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

È conveniente definire i vertici di un triangolo in termini di sistema di coordinate geografiche. Per calcolare la lunghezza di un arco di sfera data la longitudine λ e la latitudine Φ delle sue estremità possiamo usare la formula:

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

, dove

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

o più esplicitamente:

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

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

Le due formule di base che possono essere utilizzate per risolvere un triangolo sferico sono:

  • la legge dei coseni:

\ 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

  • la legge dei seni:

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

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

Dati tre lati, è facile calcolare gli angoli usando la regola del coseno:

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}

Infine, viene definito l'eccesso sferico di un triangolo:

E = A + B + C - \ pi

Cosa c'è di interessante nella relazione tra l'eccesso sferico di un triangolo e la sua area:

S = E \ cdot R ^ 2

Quindi su una sfera unitaria, l'eccesso di un triangolo è uguale all'area di quel triangolo!

L'obiettivo

Scrivi una funzione o un programma che calcolerà l'eccesso sferico di un triangolo in gradi, date le coordinate dei vertici del triangolo. Le coordinate del vertice sono fornite in termini di sistema di coordinate geografiche.

Ogni vertice deve essere passato nella forma [latitude in degrees][N|S][longitude in degrees][E|W]. La longitudine e Eo Wpuò essere saltata quando la latitudine è 90 ie. 90N, 90S, 10N100E, 30S20WSono le descrizioni appropriate vertex, mentre 80No 55Snon lo sono.

Le latitudini e le lunghezze sono sempre intere nei casi di test.

Le risposte con errore inferiore a un grado saranno accettate (come negli esempi seguenti). Il risultato può essere reso come reale o intero quindi, per tua comodità.

Esempi

Ingresso

90N0E
0N0E
0N90E

Produzione

89.999989

Ingresso

90N
0N0E
0N90E

Produzione

89.999989

Ingresso

0N0E
0N179E
90N0E

Produzione

178.998863

Ingresso

10N10E
70N20W  
70N40E

Produzione

11.969793

In tutti i casi di test longitudine e latitudine sono numeri interi. Parsing le coordinate dei vertici è la parte del compito, quindi un vertice deve essere passata come singola stringa / letterale, non è consentito il passaggio 80N20Eda quattro parametri / stringhe: 80, N, 20, E.

Questo è garantito che i vertici sono tutti distinti e nessuno dei due vertici costituisce una coppia di punti antipodali.

punteggio

Questo è , quindi vince il codice più corto.


1
Le uscite corrette per i primi casi di test sono 90 gradi e 179 gradi. Capisco che stai dicendo che non devono essere precisi, ma quanti punti decimali di precisione sono richiesti?
Level River St,

@steveverrill Aggiornato l'attività. La precisione di un grado è sufficiente.
pawel.boczarski,

@ pawel.boczarski Le latitudini / longitudini sono sempre numeri interi?
Flawr

@flawr Sì, ho aggiornato l'attività.
pawel.boczarski,

Risposte:


4

Matlab, 288 266 byte

Ecco la versione commentata che dovrebbe spiegare cosa sta succedendo:

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

Completamente golf (le interruzioni di riga possono essere rimosse):

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

Principali cambiamenti:

Nuova costante r= 180 / PI definita e utilizzata in tutta la funzione. edoveva essere inizializzato su + PI, quindi l'eccesso ora conta verso il basso e viene annullato prima di tornare.

t[]eliminato: Ruby consente di assegnare t[]direttamente i dati a cui è stato assegnatou,v,w.

iCiclo singolo per svolgere il lavoro di due ?:operatori ternari che commutano tra attività.

Molte altre modifiche minori.

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

Richiede una matrice di 3 stringhe.

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}

Panoramica

Le lunghezze dei lati del triangolo sulla sfera dell'unità sono uguali agli angoli tra i vettori che descrivono i due punti. Ma non abbiamo bisogno di conoscere quell'angolazione. Basta conoscere il coseno dell'angolo, che può essere facilmente ottenuto dalle coordinate cartesiane usando il Prodotto Dot.

Spiegazione

Le stringhe di input vengono convertite in una rappresentazione in formato stringa di un array, che viene quindi valutato e archiviato t, come di seguito. Lo zero finale non è necessario se vengono fornite due coordinate. Se viene fornita solo la latitudine 90, lo zero viene interpretato come longitudine.

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

I prodotti Dot sono nella forma a.b=ax*bx+ay*by+az*bz. Poiché i vettori sono tutti di lunghezza unitaria, il prodotto punto è uguale al coseno dell'angolo tra i vettori.

Per calcolarli, un ciclo viene ripetuto 6 volte passando due volte attraverso i dati di input. Nelle iterazioni pari a 0,2,4 le variabili x,y,zsono impostate su 1 per iniziare un nuovo calcolo. Ad ogni iterazione, queste variabili vengono moltiplicate per i componenti x, ye z di ciascun vettore, utilizzando i dati di longitudine e latitudine memorizzati t[0],t[1](a cui vengono assegnati anche motivi di golf u,v). La somma delle variabili viene scritta in array n(i valori di Garbage su iterazioni pari vengono sovrascritti dai valori corretti su iterazioni dispari) in modo che alla fine ncontenga i prodotti a 3 punti [a.b, c.a, b.c].

Per la regola del coseno, abbiamo bisogno dei coseni dei tre angoli inclusi tra i vertici, ma abbiamo anche bisogno dei seni. Questi sono ottenuti come sqrt(1-cosine**2). Poiché i seni vengono moltiplicati insieme, è possibile riorganizzare l'espressione in modo che sqrtsia necessaria una sola chiamata a . Il fatto che non sappiamo se il seno sia positivo o negativo non importa, poiché la formula di haversine dà sempre comunque il seno positivo. L'importante quantità fisica è la distanza tra i punti, che è assoluta e quindi sempre positiva.

Per ogni iterazione i=0..2, calcoliamo il valore dell'angolo opposto all'array array i-1usando gli altri elementi ie i-2. Sottotitoli di array negativi come questo sono legali in Ruby, vanno semplicemente all'inizio dell'array.

Non registrato nel programma di test

Richiede tre serie di coordinate sulla stessa linea, con spazi tra loro.

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]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.