Zeichnen der Cornu-Spirale

33

Die Cornu-Spirale kann mit der Feynman-Methode für Pfadintegrale der Lichtausbreitung berechnet werden. Wir werden dieses Integral annähern die folgende Diskretisierung verwendet.

Betrachten Sie einen Spiegel wie in diesem Bild, wo Ssich die Lichtquelle befindet und Pwo wir Licht sammeln. Wir nehmen an, dass das Licht in einem geraden Strahl von Sjedem Punkt im Spiegel und dann zu jedem Punkt reflektiert wird P. Wir unterteilen den Spiegel in NSegmente, in diesem Beispiel 13 mit der Bezeichnung Abis M, so dass die Weglänge des Lichts R=SN+NP, wo SNist der Abstand Szum Spiegelsegment Nund ähnliches für P. ( Beachten Sie, dass im Bild die Entfernung von Punkten Sund Pzum Spiegel aus visuellen Gründen stark verkürzt wurde. Der Block Qist eher irrelevant und dient nur dazu, die Reflexion über den Spiegel sicherzustellen und direktes Licht von Sbis zu vermeidenP. )

Reflektierender Spiegel

Für eine gegebene Wellenzahl kann kder Zeiger eines Lichtstrahls wie folgt berechnet werden exp(i k R): Wo iist die imaginäre Einheit? Wenn alle diese Zeiger von Kopf bis Schwanz vom linken Spiegelsegment nach rechts aufgetragen werden, entsteht die Cornu-Spirale. Für 13 - Elemente und die unten beschriebenen Werte gibt:

Bildbeschreibung hier eingeben

Bei großen N, dh vielen Spiegelsegmenten nähert sich die Spirale der "wahren" Cornu-Spirale. Dieses Bild zeigt verschiedene Werte für N:

Bildbeschreibung hier eingeben

Herausforderung

Für ein gegebenes Nsei x(n)das x- Koordinatenzentrum des n- ten Spiegelsegments ( n = 0,1,2,...,N):

x(n) := n/N-0.5

Lassen SN(n)der Abstand der S = (-1/2, 1000)an den n-ten Spiegelsegment:

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

und ähnlich

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

Die vom n- ten Lichtstrahl zurückgelegte Gesamtstrecke beträgt also

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

Dann definieren wir den Zeiger (eine komplexe Zahl) des Lichtstrahls, der durch das n- te Spiegelsegment geht, als

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

Wir betrachten nun die kumulativen Summen (als Annäherung an ein Integral)

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

Das Ziel ist nun, eine stückweise lineare Kurve durch die Punkte zu zeichnen (C(0), C(1), ..., C(n)), an denen der Imaginärteil von C(n)gegen seinen Realteil aufgetragen werden soll.

Die Eingabe sollte die Anzahl der Elemente sein N, die ein Minimum von 100 und ein Maximum von mindestens 1 Million Elementen hat (mehr ist natürlich erlaubt).

Die Ausgabe sollte ein Plot oder ein Bild in einem beliebigen Format von mindestens 400 × 400 Pixel oder unter Verwendung von Vektorgrafiken sein. Die Farbe der Linie, der Achsenskala usw. ist unwichtig, solange die Form sichtbar ist.

Da dies Codegolf ist, gewinnt der kürzeste Code in Bytes.

Bitte beachten Sie, dass dies keine tatsächliche Cornu-Spirale ist, sondern eine Annäherung an diese. Das Anfangspfadintegral wurde unter Verwendung der Fresnel-Näherung angenähert, und der Spiegel hat sowohl keine unendliche Länge als auch keine unendliche Anzahl von Segmenten und wird auch nicht durch die Amplituden der einzelnen Strahlen normiert.

Adriaan
quelle
5
Ich hatte die Werte nvon 1, aber in Übereinstimmung mit Luis und Flawr, die zum Zeitpunkt des Wandels die einzigen Antwortenden waren, korrigierte ich es auf von 0, was den Spiegel symmetrisch macht und mit dem Rest der Herausforderung übereinstimmt. Entschuldigung.
Adriaan,

Antworten:

20

MATL , 29 26 25 Bytes

Vielen Dank an @Adriaan für 3 Bytes!

Q:qG/q1e3YytP+1e6j*ZeYsXG

Hier ist ein Beispiel mit Eingaben ... denn heute hat MATL seinen ersten Geburtstag! (und 2016 ist ein Schaltjahr; danke an @MadPhysicist für die Korrektur).365 366

Oder versuchen Sie es in MATL online! (experimenteller Compiler; aktualisieren Sie die Seite, wenn es nicht funktioniert).

Bildbeschreibung hier eingeben

Erläuterung

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
Luis Mendo
quelle
8
Nimmt das nächste Handtuch und wirft es in ...
Magic Octopus Urn
10
Alles Gute zum Geburtstag MATL!
Suever
1
Ist 2016 nicht ein Schaltjahr?
Mad Physicist
14

MATLAB, 88 84 81 79 Bytes

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

Vielen Dank an @LuisMendo für -3 Bytes und @Adriaan für -2 Bytes!

Die Funktion gist die Distanzfunktion, die wir in SNund verwenden NP, und hführt den Rest der Berechnung plus Plotten aus. fdie tatsächliche Funktion, die wir wollen, und sie erzeugt den Vektor, den wir brauchen.

Dies ist die Ausgabe für N=1111

Ausgabe für N = 1111

fehlerhaft
quelle
12

GeoGebra , 107 Bytes

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]]

Jede Zeile wird separat in die Eingabeleiste eingegeben. Die Eingabe erfolgt aus einem Eingabefeld.

Hier ist ein GIF der Ausführung:

Cornu-Spirale

Wie es funktioniert

Die Eingabe 1und 1E6weist implizit die Werte auf aund bsind. Als Nächstes erstellt der InputBox[a]Befehl ein Eingabefeld und ordnet es diesem zu a.

Der innere SequenceBefehl iteriert über ganzzahlige Werte von kvon 0bis aeinschließlich. Für jeden Wert von kwird der erforderliche Abstand mithilfe des Ausdrucks berechnet ((k/a)^2+b)^.5+((k/a-1)^2+b)^.5). Dies wird dann mit multipliziert i*b, wobei idie imaginäre Einheit ist, und ezum Ergebnis angehoben. Dies ergibt eine Liste komplexer Zahlen.

Danach führt der äußere Sequencedie kumulative Summierung durch, indem er über ganzzahlige Werte von lvon 1bis aeinschließlich iteriert . Für jeden Wert von lwerden die ersten lElemente der Liste mit dem SumBefehl summiert , was wiederum eine Liste komplexer Zahlen ergibt.

GeoGebra behandelt die komplexe Zahl a + bials Punkt (a, b). Daher können die komplexen Zahlen mit dem PolylineBefehl geplottet werden , der alle Punkte in der Liste der komplexen Zahlen mit geraden Liniensegmenten verbindet.

TheBikingViking
quelle
5

R, 102 82 80 Bytes

Bearbeiten: Funktion zur Entfernungsberechnung abgeschafft

Edit2: Bemerkte eine fast identische Antwort von @Plannapus (na ja)

Edit3: Dank @Plannapus auch 2 Bytes gespeichert

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

Denn N=1000wir bekommen:

Bildbeschreibung hier eingeben

Billywob
quelle
Tatsächlich können Sie bis zu 80 Byte xN=scan();x=1:N/N;plot(cumsum(exp((sqrt(x^2+1e6)+sqrt((x-1)^2+1e6))*1e6i)),t="l")
groß werden,
4

R 86 83 81 Bytes

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

Vielen Dank an @JarkoDubbeldam für die zusätzlichen 3 Bytes.

Für N = 1000:

N = 1e3

Plannapus
quelle
Wow, 2 R antwortet innerhalb von 2 Minuten. Es ist seltsam, ich habe es genauso versucht und ich konnte es nicht zum Laufen bringen, aber das funktioniert gut für mich: S Wie auch immer, gute Arbeit!
JAD
Wenn Sie den Scan als solchen verwenden, werden plot(cumsum(exp(1e6i*(sqrt(1e6+(0:(N<-scan())/N)^2)+sqrt(1e6+(0:N/N-1)^2)))),t="l")einige Bytes gespart
JAD
1

Mathematica 89 Bytes (87 Zeichen)

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

Verwendung:

%@100

Ausbeuten

Bildbeschreibung hier eingeben

Kelly Lowder
quelle