Tracciare la spirale di Cornu


33

La spirale di Cornu può essere calcolata usando il metodo di Feynman per gli integrali di percorso della propagazione della luce. Approssimeremo questo integrale usando la seguente discretizzazione.

Considera uno specchio come in questa immagine, dove si Strova la fonte di luce e Pil punto in cui raccogliamo la luce. Partiamo dal presupposto che la luce rimbalza in un raggio dritto da Sogni punto nello specchio e quindi verso il punto P. Dividiamo lo specchio in Nsegmenti, in questo esempio 13, etichettati Acome M, in modo che la lunghezza del percorso della luce sia R=SN+NP, dov'è SNla distanza dal Ssegmento specchio Ne simili per P. ( Si noti che nell'immagine la distanza dei punti Se Pdello specchio è stata molto ridotta, per scopi visivi. Il blocco Qè piuttosto irrilevante e posizionato puramente per garantire la riflessione attraverso lo specchio, ed evitare la luce diretta da SaP. )

Specchio riflettente

Per un dato numero d'onda kil fasore di un raggio di luce può essere calcolato come exp(i k R), dov'è il'unità immaginaria. Tracciare tutti questi phaser dalla testa alla coda dal segmento dello specchio sinistro a destra porta alla spirale di Cornu. Per 13 elementi e i valori descritti di seguito questo dà:

inserisci qui la descrizione dell'immagine

Per grandi N, cioè molti segmenti speculari, la spirale si avvicina alla "vera" spirale di Cornu. Vedi questa immagine usando vari valori per N:

inserisci qui la descrizione dell'immagine

Sfida

Per un dato Nlasciare che x(n)essere i x centro -coordinate del n segmento di specchio -esimo ( n = 0,1,2,...,N):

x(n) := n/N-0.5

Lascia che SN(n)sia la distanza S = (-1/2, 1000)dell'ennesimo segmento speculare:

SN(n) := sqrt((x(n)-(-1/2))^2 + 1000^2) 

e similmente

NP(n) := sqrt((x(n)-1/2)^2 + 1000^2) 

Così la distanza totale percorsa dal n -esimo raggio di luce è

R(n) := SN(n) + NP(n) 

Poi definiamo il fasore (un numero complesso) del raggio di luce passa attraverso il n segmento di specchio esimo come

P(n) = exp(i * 1e6 * R(n)) 

Consideriamo ora le somme cumulative (come approssimazione a un integrale)

C(n) = P(0)+P(1)+...+P(n)

L'obiettivo è ora tracciare una curva lineare a tratti attraverso i punti (C(0), C(1), ..., C(n)), in cui la parte immaginaria C(n)dovrebbe essere tracciata rispetto alla sua parte reale.

L' input dovrebbe essere il numero di elementi N, che ha un minimo di 100 e un massimo di almeno 1 milione di elementi (ovviamente ne è consentito un numero maggiore).

L' output deve essere un grafico o un'immagine in qualsiasi formato di almeno 400 × 400 pixel o utilizzando la grafica vettoriale. Il colore della linea, la scala degli assi ecc. Non sono importanti, purché la forma sia visibile.

Dato che si tratta di code-golf, vince il codice più breve in byte.

Si noti che questa non è una vera spirale di Cornu, ma un'approssimazione ad essa. L'integrale del percorso iniziale è stato approssimato usando l'approssimazione di Fresnel, e lo specchio non è entrambi di lunghezza infinita e non contiene un numero infinito di segmenti, così come menzionato non è normalizzato dalle ampiezze dei singoli raggi.


5
Avevo i valori di ngamma 1, ma in accordo con Luis e Flawr, che erano gli unici risponditori al momento del cambiamento, l'ho corretto per essere 0, il che rende lo specchio simmetrico ed è in accordo con il resto della sfida. Scuse.
Adriaan,

Risposte:


20

MATL , 29 26 25 byte

Grazie a @Adriaan per 3 byte di sconto!

Q:qG/q1e3YytP+1e6j*ZeYsXG

Ecco un esempio con input ... perché oggi è il primo compleanno di MATL! (e il 2016 è un anno bisestile; grazie a @MadPhysicist per la correzione).365 366

Oppure provalo in MATL online! (compilatore sperimentale; aggiorna la pagina se non funziona).

inserisci qui la descrizione dell'immagine

Spiegazione

Q:q    % Input N implicitly. Push range [0 1 ... N] (row vector)
G/     % Divide by N, element-wise
q      % Subtract 1. This gives NP projected onto the x axis for each mirror element
1e3    % Push 1000. This is NP projected onto the y axis
Yy     % Hypotenuse function: computes distance NP
tP     % Duplicate, reverse. By symmetry, this is the distance SN
+      % Add. This is distance SNP for each mirror element (row vector)
1e6j   % Push 1e6*1i
*      % Multiply
Ze     % Exponential
Ys     % Cumulative sum
XG     % Plot in the complex plane

8
Afferra l'asciugamano più vicino e lo lancia in ...
Magic Octopus Urn

10
Buon compleanno MATL!
Suever,

1
Il 2016 non è un anno bisestile?
Fisico pazzo,

14

MATLAB, 88 84 81 79 byte

g=@(x)hypot(1e3,x);h=@(x)plot(cumsum(exp(1e6i*(g(x)+g(1-x)))));f=@(N)h(0:1/N:1)

Grazie @LuisMendo per -3 byte e @Adriaan per -2 byte!

La funzione gè la funzione di distanza che utilizziamo in SNe NP, e hfa il resto del calcolo più la stampa. fla funzione reale che vogliamo e produce il vettore di cui abbiamo bisogno.

Questo è l'output per N=1111

uscita per N = 1111


12

GeoGebra , 107 byte

1
1E6
InputBox[a]
Polyline[Sequence[Sum[Sequence[e^(i*b(((k/a)^2+b)^.5+((k/a-1)^2+b)^.5)),k,0,a],l],l,1,a]]

Ogni riga viene inserita separatamente nella barra di input. L'input viene prelevato da una casella di input.

Ecco una gif dell'esecuzione:

Spirale di Cornu

Come funziona

L'immissione 1e l' 1E6assegnazione implicita dei valori a ae brispettivamente. Successivamente, il InputBox[a]comando crea una casella di input e la associa a.

Il Sequencecomando interno scorre i valori interi da kda 0a ainclusivo. Per ogni valore di k, la distanza richiesta viene calcolata usando l'espressione ((k/a)^2+b)^.5+((k/a-1)^2+b)^.5). Questo viene quindi moltiplicato per i*b, dove si itrova l'unità immaginaria, e eviene elevato al risultato. Questo produce un elenco di numeri complessi.

Successivamente, l'esterno Sequenceesegue la somma cumulativa ripetendo i valori interi da lda 1a ainclusi. Per ogni valore di l, i primi lelementi dell'elenco vengono sommati usando il Sumcomando, dando di nuovo un elenco di numeri complessi.

GeoGebra considera il numero complesso a + bicome il punto (a, b). Quindi, i numeri complessi possono essere tracciati usando il Polylinecomando, che unisce tutti i punti nell'elenco dei numeri complessi con segmenti di linea retta.


5

R, 102 82 80 byte

Modifica: scartato la funzione per il calcolo della distanza

Edit2: ho notato una risposta quasi identica di @Plannapus (vabbè)

Edit3: salvato 2 byte anche con @Plannapus

N=scan();x=1:N/N;plot(cumsum(exp((sqrt(x^2+1e6)+sqrt((x-1)^2+1e6))*1e6i)),t="l")

Perché N=1000otteniamo:

inserisci qui la descrizione dell'immagine


In realtà puoi andare fino a 80 byte dal momento che non hai più bisogno delle parentesi x:N=scan();x=1:N/N;plot(cumsum(exp((sqrt(x^2+1e6)+sqrt((x-1)^2+1e6))*1e6i)),t="l")
plannapus,

4

R, 86 83 81 byte

plot(cumsum(exp(1e6i*((1e6+(0:(N<-scan())/N)^2)^.5+(1e6+(0:N/N-1)^2)^.5))),t="l")

Grazie @JarkoDubbeldam per i 3 byte extra.

Per N = 1000:

N = 1e3


Wow, 2 R risponde entro 2 minuti. È strano, ho provato lo stesso e non sono riuscito a farlo funzionare, ma questo funziona bene per me: S Comunque, buon lavoro!
JAD,

Inoltre, l'utilizzo della scansione in quanto tale plot(cumsum(exp(1e6i*(sqrt(1e6+(0:(N<-scan())/N)^2)+sqrt(1e6+(0:N/N-1)^2)))),t="l")consente di risparmiare alcuni byte
JAD,

1

Mathematica 89 byte (87 caratteri)

Graphics[Line[ReIm/@Tr/@Table[E^(I*10^6*Tr[√(10^6+(-{0,1}+j/#)^2)]),{i,0,#},{j,0,i}]]]&

Uso:

%@100

i rendimenti

inserisci qui la descrizione dell'immagine

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.