Solo quiero hacer una imagen como esta (usando tikz
o pstricks
) de reflexión y difusión de la luz:
Lo que me interesa es cómo se puede hacer esto (semi) automáticamente a través de tikz
o pstricks
:
- especificar el número (y el espaciado) de los rayos de luz entrantes equidistantes y su ángulo
- dibujar la superficie con un parámetro r que controla la "rugosidad" r=0 es como en la imagen de arriba, para r más grandes la superficie de la superficie se vuelve cada vez más rugosa (como la gráfica de una función continua lineal por partes con más y más partes si r se convierte en más grande)
- dibuje la parte reflejada de manera que la ley de reflexión (ángulos iguales) se cumpla "localmente"
Respuesta1
Aquí hay un intento enMetapost. Usando la direction x of y
macro para encontrar el ángulo de reflexión requerido.
Esto es lo que obtienes con r=0
:
Y con 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.
Si quieres hacer algo más elegante con el rayo reflejado, puedes guardarlo como un camino en lugar de simplemente dibujarlo. Esto le permite dibujar partes del mismo en diferentes colores o dibujar flechas en parte a lo largo del mismo. Como esto:
Para obtener este efecto, puedes cambiar el bucle interno de esta manera:
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
Entonces, en lugar de simplemente dibujar el rayo reflejado, esta vez lo almacené nuevamente ray[i]
(observe que usé el operador de asignación :=
para sobrescribir el valor anterior de la variable) y luego lo dibujé en tres segmentos para obtener las puntas de flecha. en lugares bonitos.
Nota: Dado que esta solución depende de la función de Metapost normaldeviate
para generar números aleatorios, le recomiendo que se ciña al sistema numérico predeterminado. Actualmente (MP versión 1.902) existe un error horrible en la forma en que los nuevos sistemas numéricos double
implementan decimal
las constantes requeridas para normaldeviate
. Como resultado, obtendrás resultados bastante sorprendentes si utilizas cualquiera de estos nuevos sistemas numéricos. he levantado unproblema para esto en el rastreador de errores MP.
Respuesta2
Supongo que nuestros TikZers se están volviendo perezosos. Esto no puede salirse con la suya sin una respuesta de TikZ :P La misma idea pero usando decoraciones (una y otra vez).
\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}
Respuesta3
Acabo de ver que todavía falta una solución de PSTricks;)
Utilizando al menos la versión 5.0 delpst-optexpEl paquete permite utilizar trayectorias arbitrarias como superficies refractivas o reflectantes.
Así es como se puede simular una superficie rugosa. Básicamente debes usar \pssavepath
(from pst-intersect
) para guardar algún camino para usarlo más tarde como superficie reflectante:
\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}