Rysowanie spirali Cornu


33

Cornu spiralna może być obliczona przy użyciu metody Feynmana do całki toru propagacji światła. Przybliżymy tę całkę, stosując następującą dyskretyzację.

Rozważmy lustro jak na tym zdjęciu, gdzie Sjest źródło światła i Ppunkt, w którym zbieramy światło. Zakładamy, że światło odbija się prostym promieniem od Skażdego punktu w lustrze, a następnie do punktu P. Dzielimy lustro w Nsegmentach, w tym przykładzie 13, oznaczonej Ana Mtak, że długość drogi światła jest R=SN+NP, gdzie SNjest odległością Sdo segmentu lustro Ni podobna P. ( Należy zauważyć, że na zdjęciu odległość punktów Si Plustra została znacznie zmniejszona, ze względów wizualnych. Blok Qjest raczej nieistotny i umieszczony wyłącznie w celu zapewnienia odbicia przez lustro i uniknięcia bezpośredniego światła od SdoP. )

Lustro odblaskowe

Dla danej liczby falowej fazorów z promień światła może być obliczona , w którym to jednostka urojona. Wykreślenie tych wszystkich fazorów od lewej do prawej prowadzi do spirali Cornu. W przypadku 13 elementów i wartości opisanych poniżej daje to:kexp(i k R)i

wprowadź opis zdjęcia tutaj

W przypadku dużych N, tj. Wielu segmentów lustrzanych, spirala zbliża się do „prawdziwej” spirali Cornu. Zobacz ten obraz przy użyciu różnych wartości dla N:

wprowadź opis zdjęcia tutaj

Wyzwanie

Dla danej Nniech x(n)będzie współrzędnym x środka n-tego lustrzanego segmentu ( n = 0,1,2,...,N):

x(n) := n/N-0.5

Niech SN(n)będzie odległością od S = (-1/2, 1000)n-tego segmentu lustrzanego:

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

i podobnie

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

Zatem całkowita odległość przebyta przez n- ty promień światła wynosi

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

Następnie definiujemy fazor (liczbę zespoloną) promienia świetlnego przechodzącego przez n- ty segment lustrzany jako

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

Teraz bierzemy pod uwagę sumy skumulowane (jako przybliżenie całki)

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

Cel polega teraz na wykreśleniu częściowej krzywej liniowej przez punkty (C(0), C(1), ..., C(n)), w których wyobrażona część C(n)powinna zostać narysowana względem jej rzeczywistej części.

Dane wejściowe powinny być liczbą elementów N, która ma minimum 100, a maksimum co najmniej 1 milion elementów (więcej jest oczywiście dozwolone).

The wyjściowe powinny stanowić wykres lub obraz w dowolnym formacie co najmniej 400 x 400 pikseli lub z wykorzystaniem grafiki wektorowej. Kolor linii, skala osi itp. Są nieistotne, dopóki kształt jest widoczny.

Ponieważ jest to code-golf, wygrywa najkrótszy kod w bajtach.

Należy pamiętać, że nie jest to rzeczywista spirala Cornu, ale jej przybliżenie. Początkowa całka ścieżki została aproksymowana za pomocą aproksymacji Fresnela, a lustro nie ma nieskończonej długości i nie zawiera nieskończonej liczby segmentów, a także wspomniane, że nie jest znormalizowane przez amplitudy poszczególnych promieni.


5
Miałem wartości nod 1, ale w zgodzie z Luisem i flawr, którzy byli jedynymi osobami udzielającymi odpowiedzi w chwili zmiany, poprawiłem go 0, co sprawia, że ​​lustro jest symetryczne i zgadza się z resztą wyzwania. Przeprosiny.
Adriaan,

Odpowiedzi:


20

MATL , 29 26 25 bajtów

Dzięki @Adriaan za 3 bajty wyłączone!

Q:qG/q1e3YytP+1e6j*ZeYsXG

Oto przykład z danymi wejściowymi 365 366 danymi ... ponieważ dziś są pierwsze urodziny MATL! (a 2016 to rok przestępny; dzięki @MadPhysicist za korektę).

Lub wypróbuj w MATL online! (eksperymentalny kompilator; odśwież stronę, jeśli nie działa).

wprowadź opis zdjęcia tutaj

Wyjaśnienie

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
Chwyta najbliższy ręcznik i rzuca go ...
Urna Magicznej Ośmiornicy

10
Happy Birthday MATL!
Suever,

1
Czy 2016 nie jest rokiem przestępnym?
Szalony fizyk,

14

MATLAB, 88 84 81 79 bajtów

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

Dzięki @LuisMendo za -3 bajty i @Adriaan za -2 bajty!

Ta funkcja gto funkcja odległości, której używamy w SNi NP, orazh robi resztę obliczeń powiększonej kreślenia. frzeczywistą funkcję, której chcemy, i która wytwarza wektor, którego potrzebujemy.

To jest wynik dla N=1111

wyjście dla N = 1111


12

GeoGebra , 107 bajtów

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

Każda linia jest wprowadzana osobno do paska wprowadzania. Dane wejściowe są pobierane z pola wprowadzania.

Oto gif z wykonania:

Spirala Cornu

Jak to działa

Wprowadzanie 1i 1E6niejawne przypisywanie wartości do ai bodpowiednio. Następnie InputBox[a]polecenie tworzy pole wprowadzania i kojarzy jea .

Wewnętrzne Sequencepolecenie przechodzi przez wartości całkowite kod 0do awłącznie. Dla każdej wartości kwymagana odległość jest obliczana za pomocą wyrażenia ((k/a)^2+b)^.5+((k/a-1)^2+b)^.5). To jest następnie mnożone przez i*b, gdzie ijest urojoną jednostką, ie jest podnoszone do wyniku. To daje listę liczb zespolonych.

Następnie zewnętrzny Sequencewykonuje sumowanie sumujące, iterując wartości całkowite lod 1do awłącznie. Dla każdej wartości lpierwsze lelementy listy są sumowane za pomocą Sumpolecenia, ponownie uzyskując listę liczb zespolonych.

GeoGebra traktuje liczbę zespoloną a + bijako punkt (a, b). Dlatego liczby zespolone można wykreślić za pomocą Polylinepolecenia, które łączy wszystkie punkty na liście liczb zespolonych segmentami linii prostych.


5

R, 102 82 80 bajtów

Edycja: usunięto funkcję obliczania odległości

Edycja2: Zauważyłem prawie identyczną odpowiedź @Plannapus (no cóż)

Edit3: Zaoszczędź 2 bajty dzięki @Plannapus

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

Dla N=1000otrzymujemy:

wprowadź opis zdjęcia tutaj


W rzeczywistości możesz przejść nawet do 80 bajtów, ponieważ nie potrzebujesz już nawiasów wokół 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 bajtów

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

Dzięki @JarkoDubbeldam za dodatkowe 3 bajty.

Dla N = 1000:

N = 1e3


Wow, 2 odpowiedzi R w ciągu 2 minut. Dziwne, próbowałem tego samego i nie udało mi się go uruchomić, ale dla mnie to działa dobrze: S W każdym razie, dobra robota!
JAD

Ponadto użycie skanowania jako takiego plot(cumsum(exp(1e6i*(sqrt(1e6+(0:(N<-scan())/N)^2)+sqrt(1e6+(0:N/N-1)^2)))),t="l")pozwala zaoszczędzić kilka bajtów
JAD

1

Mathematica 89 bajtów (87 znaków)

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

Stosowanie:

%@100

plony

wprowadź opis zdjęcia tutaj

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.