Automatisches Generieren von Grafiken, die die Lichtstreuung auf einer rauen Oberfläche zeigen

Automatisches Generieren von Grafiken, die die Lichtstreuung auf einer rauen Oberfläche zeigen

tikzIch möchte einfach (mit oder pstricks) ein Bild von Lichtreflexion und -streuung wie dieses erstellen :

Lichtstreuung

Mich interessiert, wie dies (halb)automatisch über tikzoder erfolgen kann pstricks:

  • Geben Sie die Anzahl (und den Abstand) der gleich weit entfernten einfallenden Lichtstrahlen und ihren Winkel an.
  • Zeichnen Sie die Oberfläche mit einem Parameter r, der die „Rauhigkeit“ steuert. r=0 ist wie im Bild oben, bei größeren r wird die Oberfläche immer rauer (wie der Graph einer stückweise linearen kontinuierlichen Funktion mit immer mehr Teilen, wenn r größer wird).
  • Zeichnen Sie den reflektierten Teil so, dass das Gesetz der Reflexion (gleiche Winkel) "lokal" erfüllt ist

Antwort1

Hier ist ein Versuch inMetapost. Mithilfe des direction x of yMakros den benötigten Reflexionswinkel ermitteln.

Folgendes erhalten Sie mit r=0:

Bildbeschreibung hier eingeben

Und mit r=0.33:

Bildbeschreibung hier eingeben

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.

Wenn Sie mit dem reflektierten Strahl etwas Ausgefalleneres machen möchten, können Sie ihn als Pfad speichern, anstatt ihn einfach zu zeichnen. Auf diese Weise können Sie Teile davon in verschiedenen Farben zeichnen oder auf einem Teil des Weges Pfeile zeichnen. So:

Bildbeschreibung hier eingeben

Um diesen Effekt zu erzielen, können Sie die innere Schleife wie folgt ändern:

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   

Anstatt einfach den reflektierten Strahl zu zeichnen, habe ich ihn dieses Mal wieder gespeichert ray[i](beachten Sie, dass ich den Zuweisungsoperator verwendet habe, :=um den vorherigen Wert der Variablen zu überschreiben) und ihn anschließend in drei Segmenten gezeichnet, um die Pfeilspitzen an schönen Stellen zu bekommen.

Notiz: Da diese Lösung auf der Funktion von Metapost normaldeviatezur Generierung von Zufallszahlen beruht, empfehle ich, beim Standardzahlensystem zu bleiben. Derzeit (MP-Version 1.902) gibt es einen schrecklichen Fehler in der Art und Weise, wie die neuen Zahlensysteme die für erforderlichen Konstanten implementieren double. Infolgedessen erhalten Sie ziemlich wilde Ergebnisse, wenn Sie eines dieser neuen Zahlensysteme verwenden. Ich habe einedecimalnormaldeviateProblem hierzu im MP Bugtracker.

Antwort2

Ich schätze, unsere TikZer werden langsam faul. Das geht nicht ohne eine TikZ-Antwort :P Dieselbe Idee, aber mit Dekorationen (immer und immer wieder).

\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}

Bildbeschreibung hier eingeben

Antwort3

Ich habe gerade gesehen, dass immer noch eine PSTricks-Lösung fehlt ;)

Verwenden Sie mindestens Version 5.0 despst-optexpDas Paket ermöglicht die Verwendung beliebiger Pfade als brechende oder reflektierende Oberflächen.

So können Sie eine raue Oberfläche simulieren. Grundsätzlich müssen Sie \pssavepath(von pst-intersect) verwenden, um einen Pfad zu speichern, der später als reflektierende Oberfläche verwendet werden soll:

Bildbeschreibung hier eingeben

\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}

verwandte Informationen