Я просто хочу создать такое изображение (используя tikz
или pstricks
) отражения и рассеивания света:
Меня интересует, как это можно сделать (полу)автоматически с помощью tikz
или pstricks
:
- указать количество (и интервал) равноудаленных входящих световых лучей и их угол
- нарисуйте поверхность с параметром r, который управляет «шероховатостью» r=0, как на рисунке выше, при больших r поверхность становится все более и более шероховатой (как график кусочно-линейной непрерывной функции со все большим количеством частей, если r становится больше)
- нарисуйте отраженную часть так, чтобы закон отражения (равные углы) выполнялся «локально»
решение1
Вот попытка вМетапост. Использование direction x of y
макроса для нахождения необходимого угла отражения.
Вот что вы получаете r=0
:
И с 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.
Если вы хотите сделать что-то более затейливое с отраженным лучом, вы можете сохранить его как путь, а не просто нарисовать. Это позволяет вам рисовать его части разными цветами или рисовать стрелки на части пути вдоль него. Вот так:
Чтобы получить этот эффект, вы можете изменить внутренний цикл следующим образом:
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
Поэтому вместо того, чтобы просто нарисовать отраженный луч, на этот раз я сохранил его обратно ray[i]
(обратите внимание, что я использовал оператор присваивания :=
, чтобы перезаписать предыдущее значение переменной), а затем нарисовал его тремя сегментами, чтобы расположить наконечники стрелок в удобных местах.
Примечание: Поскольку это решение зависит от функции Metapost normaldeviate
для генерации случайных чисел, я рекомендую вам придерживаться системы счисления по умолчанию. В настоящее время (версия MP 1.902) есть ужасная ошибка в том, как новые системы счисления double
и decimal
реализуют константы, необходимые для normaldeviate
. В результате вы получите довольно дикие результаты, если вы используете любую из этих новых систем счисления. Я поднялпроблема для этого в MP bug tracker.
решение2
Наши TikZers, я полагаю, ленятся. Это не может обойтись без ответа TikZ :P Та же идея, но с использованием украшений (снова и снова).
\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}
решение3
Я только что увидел, что решения PSTricks все еще не хватает ;)
Использование как минимум версии 5.0pst-optexpПакет позволяет использовать произвольные пути в качестве преломляющих или отражающих поверхностей.
Вот как можно имитировать шероховатую поверхность. По сути, вам нужно использовать \pssavepath
(из pst-intersect
), чтобы сохранить некоторый путь для использования позже в качестве отражающей поверхности:
\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}