Só quero fazer uma imagem assim (usando tikz
ou pstricks
) de reflexão e difusão de luz:
O que me interessa é como isso pode ser feito (semi) automaticamente via tikz
ou pstricks
:
- especifique o número (e espaçamento) de raios de luz incidentes equidistantes e seu ângulo
- desenhar a superfície com um parâmetro r que controla a "rugosidade" r = 0 é como na imagem acima, para r's maiores a superfície da fonte se torna cada vez mais áspera (como o gráfico de uma função contínua linear por partes com mais e mais partes se r se tornar maior)
- desenhe a parte refletida de modo que a reflexão da lei (ângulos iguais) seja satisfeita "localmente"
Responder1
Aqui está uma tentativa deMetapost. Usando a direction x of y
macro para encontrar o ângulo de reflexão necessário.
Aqui está o que você ganha r=0
:
E com r=0.33
:
prologues := 3;
outputtemplate := "%j%c.eps";
beginfig(1);
path base, ray[]; u = 5mm;
r=0.33;
base = (-6u,0) for x=-5.8u step 0.2u until 5.8u: -- (x,r*normaldeviate) endfor -- (6u,0);
draw base
-- point infinity of base shifted (0,-u)
-- point 0 of base shifted (0,-u) -- cycle
withcolor .67 red;
theta = -45;
for i=-2 upto 2:
ray[i] = (left--right) scaled 6u rotated theta shifted (i*u,0);
b := ypart(ray[i] intersectiontimes base);
drawarrow point 0 of ray[i]
-- point b of base
-- point 0 of ray[i] reflectedabout(point b of base, direction b of base
shifted point b of base
rotatedabout(point b of base, 90));
endfor
label.urt("r=" & decimal r, point 0 of base);
endfig;
end.
Se quiser fazer algo mais sofisticado com o raio refletido, você pode salvá-lo como um caminho em vez de apenas desenhá-lo. Isso permite que você desenhe partes dele em cores diferentes ou desenhe setas ao longo dele. Assim:
Para obter esse efeito, você pode alterar o loop interno assim:
for i=-2 upto 2:
ray[i] = (left--right) scaled 6u rotated theta shifted (i*u,0);
b := ypart(ray[i] intersectiontimes base);
ray[i] := point 0 of ray[i]
-- point b of base
-- point 0 of ray[i] reflectedabout(point b of base, direction b of base
shifted point b of base
rotatedabout(point b of base, 90));
drawarrow subpath(0,0.3) of ray[i];
drawarrow subpath(0.3,1.7) of ray[i];
draw subpath(1.7,infinity) of ray[i];
endfor
Então, em vez de apenas desenhar o raio refletido, desta vez eu o armazenei de volta ray[i]
(observe que usei o operador de atribuição :=
para substituir o valor anterior da variável) e depois desenhei-o em três segmentos para obter as pontas das setas em lugares legais.
Observação: Como esta solução depende da função do Metapost normaldeviate
para gerar números aleatórios, recomendo que você siga o sistema numérico padrão. Existe atualmente (MP versão 1.902) um bug horrível na forma como os novos sistemas numéricos double
e decimal
implementam as constantes necessárias para normaldeviate
. Como resultado, você obterá resultados bastante selvagens se usar qualquer um desses novos sistemas numéricos. Eu levantei umproblema para isso no rastreador de bugs do MP.
Responder2
Nossos TikZers estão ficando preguiçosos, eu acho. Isso não pode acontecer sem uma resposta do TikZ: P Mesma ideia, mas usando decorações (repetidas vezes).
\documentclass[tikz]{standalone}
\usetikzlibrary{decorations.pathmorphing,decorations.markings,calc}
\begin{document}
\begin{tikzpicture}
\shadedraw[thick,top color=gray!10,bottom color=gray,
postaction=decorate,
decoration={markings,
mark= between positions 1cm and 3cm step 5mm with {% Places five of them
\node[transform shape,inner sep=1pt]
(mark-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) {};
}
}
]{
decorate[decoration={random steps,segment length=1.5mm,amplitude=1pt}]%Roughness is amplitude
{
(0,0) -- ++(4,0)
}
} -- ++(0,-5mm) -- ++(-4cm,0) -- cycle;
\foreach \x in {1,2,...,5}{
\draw[postaction=decorate,
decoration={markings,
mark=between positions 0.25 and 0.75 step 0.5 with{\arrow{latex}}
}]
(mark-\x.center)+(135:2cm) --(mark-\x.center)
--($(mark-\x.north west)!2cm!45:(mark-\x.north east)$);
}
\end{tikzpicture}
\end{document}
Responder3
Acabei de ver que ainda falta uma solução PSTricks;)
Usando pelo menos a versão 5.0 dopst-optexpO pacote permite usar caminhos arbitrários como superfícies refrativas ou reflexivas.
Veja como você pode simular uma superfície áspera. Basicamente você deve usar \pssavepath
(from pst-intersect
) para salvar algum caminho para ser usado posteriormente como superfície reflexiva:
\documentclass[margin=5pt, pstricks]{standalone}
\usepackage{pst-optexp}
\makeatletter
\newOptexpTripole{roughsurface}
\def\roughsurface@nodes{%
\pssavepath[linestyle=none, arrows=-,ArrowInside=-]{\oenode@Path{A}}{%
\code{0 srand}% provides reproducable results
\moveto(!-3 Rand 0.5 sub 0.1 mul)
\multido{\r=-2.7+0.3}{20}{%
\lineto(!\r\space Rand 0.5 sub 0.1 mul)}%
}%
\newOptexpComp{%
{0 0} tx@IntersectDict /\PIT@name{\oenode@Path{A}} get 0 0 refl {PathIfc}
1 }%
}%
\def\roughsurface@comp{%
\pstracecurve{\oenode@Path{A}}
}%
\makeatother
\begin{document}
\begin{pspicture}(10,3)
\optplane[angle=90](1,3)
\roughsurface(0,3)(5,0)(10,3)
\addtopsstyle{Beam}{beamalign=abs, beamangle=-45, arrows=->, arrowscale=2}
\multido{\r=0+0.3}{6}{%
\drawbeam[beampos=\r]{1}{2}{1}}
\end{pspicture}
\end{document}