Traçando a espiral de Cornu

33

A espiral de Cornu pode ser calculada usando o método de Feynman para integrais de caminho da propagação da luz. Vamos aproximar essa integral usando a seguinte discretização.

Considere um espelho como nesta imagem, onde Sestá a fonte de luz e Po ponto em que coletamos a luz. Assumimos que a luz salta em um raio reto de Scada ponto no espelho e depois para apontar P. Dividimos o espelho em Nsegmentos, neste exemplo 13, rotulados Acomo M, para que o comprimento do caminho da luz seja R=SN+NP, onde SNestá a distância do Ssegmento do espelho Ne semelhante para P. ( Note que na imagem a distância de pontos Se Ppara o espelho foi encurtado muito, para efeitos visuais. O bloco Qé bastante irrelevante, e colocou puramente para garantir reflexão através do espelho, e evitar a luz direta SparaP. )

Espelho refletindo

Para um dado número de onda, ko fasor de um raio de luz pode ser calculado como exp(i k R), onde iestá a unidade imaginária. A plotagem de todos esses fasores da cabeça para a cauda, ​​do segmento de espelho esquerdo para a direita, leva à espiral de Cornu. Para 13 elementos e os valores descritos abaixo, isso fornece:

insira a descrição da imagem aqui

Para grandes Nsegmentos de espelhos, isto é, a espiral se aproxima da "verdadeira" espiral de Cornu. Veja esta imagem usando vários valores para N:

insira a descrição da imagem aqui

Desafio

Para um dado Ndeixe x(n)ser os x centro da coordenada x n segmento de espelho -ésimo ( n = 0,1,2,...,N):

x(n) := n/N-0.5

Seja SN(n)a distância do S = (-1/2, 1000)n-ésimo segmento de espelho:

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

e da mesma forma

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

Portanto, a distância total percorrida pelo n- ésimo raio de luz é

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

Em seguida, definimos o fasor (um número complexo) do raio de luz que passa pelo n- ésimo segmento de espelho como

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

Agora, consideramos as somas cumulativas (como uma aproximação a uma integral)

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

O objetivo agora é traçar uma curva linear por partes através dos pontos (C(0), C(1), ..., C(n)), onde a parte imaginária C(n)deve ser plotada em relação à sua parte real.

A entrada deve ser o número de elementos N, que tem um mínimo de 100 e um máximo de pelo menos 1 milhão de elementos (é claro que é permitido mais).

A saída deve ser uma plotagem ou imagem em qualquer formato de pelo menos 400 × 400 pixels ou usando gráficos vetoriais. A cor da linha, a escala dos eixos etc. não são importantes, desde que a forma seja visível.

Como esse é o código-golfe, o código mais curto em bytes vence.

Observe que esta não é uma espiral real de Cornu, mas uma aproximação a ela. A integral do caminho inicial foi aproximada usando a aproximação de Fresnel, e o espelho não é de comprimento infinito nem contém um número infinito de segmentos, assim como mencionado, não é normalizado pelas amplitudes dos raios individuais.

Adriaan
fonte
5
Eu tinha os valores de nvariar de 1, mas, de acordo com Luis e flawr, que eram os únicos responsáveis ​​pela resposta no momento da mudança, eu o corrigi 0, o que torna o espelho simétrico e está de acordo com o resto do desafio. Desculpas.
Adriaan 12/12

Respostas:

20

MATL , 29 26 25 bytes

Graças a @Adriaan por 3 bytes de desconto!

Q:qG/q1e3YytP+1e6j*ZeYsXG

Aqui está um exemplo com entrada ... porque hoje é o primeiro aniversário do MATL! (e 2016 é um ano bissexto; obrigado a @MadPhysicist pela correção).365 366

Ou experimente no MATL online! (compilador experimental; atualize a página se não funcionar).

insira a descrição da imagem aqui

Explicação

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
fonte
8
Agarra a toalha mais próxima e joga-lo em ...
Magia Octopus Urna
10
Feliz Aniversário MATL!
Suever 12/12
1
2016 não é um ano bissexto?
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)

Obrigado @LuisMendo por -3 bytes e @Adriaan por -2 bytes!

A função gé a função de distância em que usamos SNe NP, e hfaz o restante do cálculo mais a plotagem. fa função real que queremos e produz o vetor que precisamos.

Essa é a saída para N=1111

saída para N = 1111

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

Cada linha é inserida separadamente na barra de entrada. A entrada é obtida de uma caixa de entrada.

Aqui está um gif da execução:

Espiral de Cornu

Como funciona

Inserir 1e 1E6atribuir implicitamente os valores a ae brespectivamente. Em seguida, o InputBox[a]comando cria uma caixa de entrada e a associa a.

O Sequencecomando interno itera sobre valores inteiros de kde 0até ainclusivo. Para cada valor de k, a distância necessária é calculada utilizando a expressão ((k/a)^2+b)^.5+((k/a-1)^2+b)^.5). Isso é multiplicado por i*bonde iestá a unidade imaginária e eelevado ao resultado. Isso produz uma lista de números complexos.

Depois disso, o externo Sequenceexecuta a soma cumulativa iterando sobre valores inteiros de lde 1até ainclusivo. Para cada valor de l, os primeiros lelementos da lista são somados usando o Sumcomando, produzindo novamente uma lista de números complexos.

O GeoGebra trata o número complexo a + bicomo o ponto (a, b). Portanto, os números complexos podem ser plotados usando o Polylinecomando, que une todos os pontos da lista de números complexos com segmentos de linha reta.

TheBikingViking
fonte
5

R, 102 82 80 bytes

Editar: descartou a função para calcular a distância

Edit2: Notou uma resposta quase idêntica por @Plannapus (oh bem)

Edit3: salvou 2 bytes graças ao @Plannapus também

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

Pois N=1000temos:

insira a descrição da imagem aqui

Billywob
fonte
Na verdade, você pode ter até 80 bytes, já que não precisa mais dos parênteses 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 bytes

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

Obrigado a @JarkoDubbeldam pelos 3 bytes extras.

Para N = 1000:

N = 1e3

plannapus
fonte
Uau, 2 R responde dentro de 2 minutos. É estranho, tentei o mesmo e não consegui fazê-lo funcionar, mas isso funciona bem para mim: S De qualquer forma, bom trabalho!
JD
Além disso, o uso de scan como tal plot(cumsum(exp(1e6i*(sqrt(1e6+(0:(N<-scan())/N)^2)+sqrt(1e6+(0:N/N-1)^2)))),t="l")economiza alguns bytes
JAD
1

Mathematica 89 bytes (87 caracteres)

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

Uso:

%@100

rendimentos

insira a descrição da imagem aqui

Kelly Lowder
fonte