209 lines
19 KiB
HTML
209 lines
19 KiB
HTML
<!DOCTYPE html>
|
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="generator" content="pandoc" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
|
<title>cw1</title>
|
|
<style>
|
|
code{white-space: pre-wrap;}
|
|
span.smallcaps{font-variant: small-caps;}
|
|
span.underline{text-decoration: underline;}
|
|
div.column{display: inline-block; vertical-align: top; width: 50%;}
|
|
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
|
|
ul.task-list{list-style: none;}
|
|
pre > code.sourceCode { white-space: pre; position: relative; }
|
|
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
|
|
pre > code.sourceCode > span:empty { height: 1.2em; }
|
|
code.sourceCode > span { color: inherit; text-decoration: inherit; }
|
|
div.sourceCode { margin: 1em 0; }
|
|
pre.sourceCode { margin: 0; }
|
|
@media screen {
|
|
div.sourceCode { overflow: auto; }
|
|
}
|
|
@media print {
|
|
pre > code.sourceCode { white-space: pre-wrap; }
|
|
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
|
|
}
|
|
pre.numberSource code
|
|
{ counter-reset: source-line 0; }
|
|
pre.numberSource code > span
|
|
{ position: relative; left: -4em; counter-increment: source-line; }
|
|
pre.numberSource code > span > a:first-child::before
|
|
{ content: counter(source-line);
|
|
position: relative; left: -1em; text-align: right; vertical-align: baseline;
|
|
border: none; display: inline-block;
|
|
-webkit-touch-callout: none; -webkit-user-select: none;
|
|
-khtml-user-select: none; -moz-user-select: none;
|
|
-ms-user-select: none; user-select: none;
|
|
padding: 0 4px; width: 4em;
|
|
color: #aaaaaa;
|
|
}
|
|
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
|
|
div.sourceCode
|
|
{ }
|
|
@media screen {
|
|
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
|
|
}
|
|
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
|
|
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
|
|
code span.at { color: #7d9029; } /* Attribute */
|
|
code span.bn { color: #40a070; } /* BaseN */
|
|
code span.bu { } /* BuiltIn */
|
|
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
|
|
code span.ch { color: #4070a0; } /* Char */
|
|
code span.cn { color: #880000; } /* Constant */
|
|
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
|
|
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
|
|
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
|
|
code span.dt { color: #902000; } /* DataType */
|
|
code span.dv { color: #40a070; } /* DecVal */
|
|
code span.er { color: #ff0000; font-weight: bold; } /* Error */
|
|
code span.ex { } /* Extension */
|
|
code span.fl { color: #40a070; } /* Float */
|
|
code span.fu { color: #06287e; } /* Function */
|
|
code span.im { } /* Import */
|
|
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
|
|
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
|
|
code span.op { color: #666666; } /* Operator */
|
|
code span.ot { color: #007020; } /* Other */
|
|
code span.pp { color: #bc7a00; } /* Preprocessor */
|
|
code span.sc { color: #4070a0; } /* SpecialChar */
|
|
code span.ss { color: #bb6688; } /* SpecialString */
|
|
code span.st { color: #4070a0; } /* String */
|
|
code span.va { color: #19177c; } /* Variable */
|
|
code span.vs { color: #4070a0; } /* VerbatimString */
|
|
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
|
|
</style>
|
|
<link rel="stylesheet" href="style.css" />
|
|
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js" type="text/javascript"></script>
|
|
<!--[if lt IE 9]>
|
|
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
|
|
<![endif]-->
|
|
</head>
|
|
<body>
|
|
<h1 id="l-system">L-System</h1>
|
|
<p>W tej części zajęć skupimy się na tworzeniu L-Systemów i wykorzystaniu ich do reprezentacji zjawisk przyrodniczych.</p>
|
|
<blockquote>
|
|
<p><strong>Przypomnienie</strong> <strong>L-System</strong> to system przepisywania i gramatyka formalna. Składa się z: symboli, które tworzą ciągi znaków; reguł produkcyjnych, które opisują na co należy przepisać dany znak; aksjomatu, czyli początkowego ciągu znaków; i mechanizmu, który tłumaczy ciąg znaków na reprezentacje geometryczną</p>
|
|
</blockquote>
|
|
<p>Bazą dla tych zajęć jest książka Algorithmic Beauty of Plants dostępna za darmo pod <a href="http://algorithmicbotany.org/papers/abop/abop.lowquality.pdf">linkiem</a> lub <a href="http://algorithmicbotany.org/papers/abop/abop.pdf">w wyższej jakości</a></p>
|
|
<h2 id="składnia-l-systemów">Składnia L-Systemów</h2>
|
|
<p>Projekt zawiera bibliotekę, która interpretuje L-Systemy. Ich definicję pobiera z oddzielnego pliku. Ich składnie opisuję definicja L-Systemu opisującego rozwój bakterii Anabaena znajduje się w projekcie pod ścieżką <code>Assets\LSystem\Anabaena.txt</code> i wygląda następująco:</p>
|
|
<pre><code>#axiom
|
|
L
|
|
#rules
|
|
L->lR
|
|
R->Lr
|
|
l->L
|
|
r->R
|
|
#end rules</code></pre>
|
|
<p>Plik należy zacząć od linii <code>#axiom</code>, następnie w następnej linii zamieścić ciąg początkowy. Później pomiędzy liniami <code>#rules</code> i <code>#end rules</code> umieścić instrukcje przepisywania według zasady: <code><znak przepisywany>-><wynik przepisania></code> każdy znak przed strzałką i po strzałce (z wyjątkiem reguł o których później) jest traktowany jako następny symbol. W przypadku kilku reguł, które dotyczą tego samego symbolu wykona się ta, która jest wyżej w pliku. Między reguły można dodawać komentarze, znakiem komentującym jest <code>#</code>. Jeżeli znak nie posiada żadnej reguły, która by go opisywała, to nie jest on zmieniany.</p>
|
|
<p>Odpal scenę <strong>LSystemFromFile</strong>, zaznacz <strong>LSystemController</strong> w panelu po prawej. Po lewej w polu <strong>L System Path</strong> wpisz <code>Assets\LSystem\Anabaena.txt</code> kliknij <strong>Load File</strong>, by załadować LSystem. Następnie Evaluate, by wykonać przepisanie. W scenie wyświetlą się obiekty reprezentujące symbole a w konsoli wyświetli się wynik przepisania.</p>
|
|
<p>Składnia wszystkich rozszerzeń jest zaprezentowana w pliku <code>SampleLSystem.txt</code> w tej chwili niektóre reguły mogą byc niezrozumiałe, ale może się on przydać później jako wzorzec.</p>
|
|
<h2 id="turtle-graphics">Turtle Graphics</h2>
|
|
<p>Turtle Graphics jest metodą tworzenia grafiki komputerowej, wykorzystuje kursor (tytułowego żółwia) wykonujący instrukcje w przestrzeni lokalnej.</p>
|
|
<figure>
|
|
<img src="Turtle-animation-20210313143359379.gif" alt="https://en.wikipedia.org/wiki/Turtle_graphics" /><figcaption aria-hidden="true">https://en.wikipedia.org/wiki/Turtle_graphics</figcaption>
|
|
</figure>
|
|
<p>L-Systemy można interpretować za pomocą Turtle Graphics, poprzez przypisanie każdemu symbolowi instrukcji jaką ma wykonać żółw. Następnie żółw będzie wykonywał kolejne instrukcje czytając napis od lewej do prawej.</p>
|
|
<p>Na początek zaczniemy od prostej reprezentacji, gdzie <code>+</code> będzie oznaczał w kierunku zgodnym z ruchem wskazówek zegara o wskazany kąt, natomiast <code>-</code> w przeciwnym. Kąt zwyczajowo oznacza się grecką literą <span class="math inline">\(\delta\)</span>. Każdy inny symbol będzie oznaczał idź prosto o 1.</p>
|
|
<p>Odpal Scenę LSystem2D, załaduj plik <code>Sierpinski.txt</code>, ustaw kąt na 60 stopni i wykonaj kilka kroków.</p>
|
|
<h3 id="zadanie">Zadanie</h3>
|
|
<p>napisz Lsystem, który będzie rysował gwiazdkę kocha</p>
|
|
<ol type="1">
|
|
<li><h4 id="krzywa-kocha">Krzywa kocha:</h4></li>
|
|
</ol>
|
|
<p><img src="../../../../Downloads/Wirtualne Światy treść zadań/Kochsim.gif" /></p>
|
|
<p><img src="../../../../Downloads/Wirtualne Światy treść zadań/RPReplay_Final1615641331.gif" style="zoom:50%;" /></p>
|
|
<p>Opis:</p>
|
|
<ol type="1">
|
|
<li>Podziel linię na 3 równę części</li>
|
|
<li>Przy środkowej części narysuj równoboczny trójkąt zwrócony na zewnątrz</li>
|
|
<li>Usuń środkową część pierwotnej lini</li>
|
|
</ol>
|
|
<p>Musimy z jednej lini zrobić 4 nowe, z czego pierwsza i ostatnia idą w tym samym kierunku, a dwie środkowe idą pod innym kątem (podpowiedź: dając dwa razy + lub - możesz zwiększyć kąt)</p>
|
|
<ol start="2" type="1">
|
|
<li><h4 id="w-pierwszym-kroku-l-systemu-utwórz-trójkąt">W pierwszym kroku L-Systemu utwórz trójkąt</h4>
|
|
<img src="Von_Koch_curve.gif" /></li>
|
|
</ol>
|
|
<h2 id="bracketed-l-systems">Bracketed L-systems</h2>
|
|
<p>W podstawowej wersji L-Systemy są pojedyńczym ciągiem znaków, by uzyskać możliwość tworzenia rozgałęzień wprowadzamy dwa specjalne znaki <code>[</code> oraz <code>]</code> pierwszy mówi, żeby zapamiętać obecny stan, drugi oznacza by wrócić do stanu zapamiętanym przy ostatnim znaku <code>[</code>. Przykładowo ciąg symboli <code>F[+FFF][-F]FF</code> dla <span class="math inline">\(\delta=90\)</span> będzie reprezentowany następująco <img src="im_bracketed-5642437.jpg" alt="obraz" /></p>
|
|
<h3 id="zadanie-1">Zadanie</h3>
|
|
<p>Wyświetl poniższe L-Systemy. Zmodyfikuj definicję drugiego, by dodstać asymetryczną roślinę.</p>
|
|
<p><img src="bracketed zad 1.JPG" alt="Screenshot 2021-03-13 at 14.29.06" /> <img src="Screenshot%202021-03-13%20at%2014.29.10.png" alt="Screenshot 2021-03-13 at 14.29.10" /></p>
|
|
<h2 id="pisanie-własnej-interpretacji-lsystemów">Pisanie własnej interpretacji LSystemów</h2>
|
|
<p>Wróćmy do sceny LSystemFromFile W tej scenie zamiast kresek pojawiają się figury reprezentujące komórki (czerwona lewa, zielona prawa, niska młoda, wysoka dorosła). Otwórz skrypt AnabeanaTurtle.cs, który odpowiada za rysowanie. Zawiera on klasę <code>AnabeanaTurtle</code> dziedziczącą po <code>TurtleLSystem</code>. <code>TurtleLSystem</code> jest klasą abstrakcyjną, wymaga zdefiniowania funkcji <code>initLiteralInterpretation</code>, w której należy opisać jak interpretować symbole.</p>
|
|
<div class="sourceCode" id="cb2"><pre class="sourceCode cs"><code class="sourceCode cs"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a> <span class="kw">protected</span> <span class="kw">override</span> <span class="dt">void</span> <span class="fu">initLiteralInterpretation</span>() {</span>
|
|
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> turtleInterpretation = <span class="kw">new</span> Dictionary<<span class="dt">string</span>, Func<<span class="dt">float</span>[], Tuple<GameObject, Matrix4x4>>>();</span>
|
|
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="co">//turtleInterpretation</span></span>
|
|
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">var</span> transformation = Matrix4x4.<span class="fu">Translate</span>(<span class="kw">new</span> <span class="fu">Vector3</span>(<span class="fl">0.0f</span>, <span class="fl">0.1f</span>, <span class="dv">0</span>)) * Matrix4x4.<span class="fu">Scale</span>(<span class="kw">new</span> <span class="fu">Vector3</span> (<span class="fl">0.05f</span>, <span class="fl">0.1f</span>, <span class="fl">0.05f</span>));</span>
|
|
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a></span>
|
|
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> turtleInterpretation.<span class="fu">Add</span>(<span class="st">"+"</span>, (<span class="dt">float</span>[] args) => <span class="kw">new</span> Tuple<GameObject, Matrix4x4>(<span class="kw">null</span>, Matrix4x4.<span class="fu">Rotate</span>(Quaternion.<span class="fu">Euler</span>(<span class="dv">0</span>, <span class="dv">0</span>, -angle))));</span>
|
|
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> turtleInterpretation.<span class="fu">Add</span>(<span class="st">"-"</span>, (<span class="dt">float</span>[] args) => <span class="kw">new</span> Tuple<GameObject, Matrix4x4>(<span class="kw">null</span>, Matrix4x4.<span class="fu">Rotate</span>(Quaternion.<span class="fu">Euler</span>(<span class="dv">0</span>, <span class="dv">0</span>, angle))));</span>
|
|
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a></span>
|
|
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> <span class="co">//Wildcard how to represent any other symbol</span></span>
|
|
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> turtleInterpretation.<span class="fu">Add</span>(<span class="st">"*.*"</span>, (<span class="dt">float</span>[] args) => <span class="kw">new</span> Tuple<GameObject, Matrix4x4>(obj, transformation));</span>
|
|
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> }</span></code></pre></div>
|
|
<p>Żeby tego dokonać należy uzupełnić słownik <code>turtleInterpretation</code>, którego kluczami są opisywane symbole jako stringi. Natomiast wartościami są funkcje, które przyjmują jako argument tablicę parametrów danego symbolu (o tym później) a zwracają Krotkę, której pierwszym elementem jest rysowany obiekt, natomiast drugim transformacja, jaką wykona żółw. Powyższym przykładzie obiekty są czytane z modeli a transformacja zawsze jest taka sama, czyli translacja o wektor (0.1,0,0) i skalowanie o wektor (0.1,0.1,0.1). (Skalowania nie są pamiętane przez żółwia)</p>
|
|
<p>Te funkcje są wykorzystywane przez żółwia do interpretacji ciągu symboli. Przykładowo <code>LRr</code> zostanie zinterpretowany następująco:</p>
|
|
<ul>
|
|
<li>żółw przesuwa się o 0.1 w osi X umieszcza bigL w punkcie (0.1,0,0)</li>
|
|
<li>żółw przesuwa się o 0.1 w osi X umieszcza bigR w punkcie (0.2,0,0) (ponieważ (0.1,0,0)+(0.1,0,0)=(0.2,0,0) )</li>
|
|
<li>żółw przesuwa się o 0.1 w osi X umieszcza bigL w punkcie (0.3,0,0)</li>
|
|
</ul>
|
|
<h3 id="zadanie-2">Zadanie</h3>
|
|
<p>Jak wyszukasz w internecie obrazki Anabaeny, zobaczysz, że są one często powykręcane, dodaj do macierz przekształceń obroty w osi Y o losowy kąt pomiędzy -20 a 20 stopni.</p>
|
|
<h2 id="parametryczne-l-systemy">Parametryczne L-Systemy</h2>
|
|
<p>Parametryczne L-Systemy operują na symbolach parametrycznych znakach, czyli takich, które posiadają 0 lub więcej parametrów rzeczywistych. Pozwala to przechowywać różne wewnętrzne stany obiektów. Przykładowo dla modelu Anabeany powyżej rozróżniamy tylko 2 stany, młody i dorosły. Dzięki parametrycznym L-Systemom możemy opisać wiek w sposób bardziej ciągły. Przykładowo poniższy L-System komórki która rośnie i jak osiągnie odpowiedni wiek rozdziela się na dwie młode komórki</p>
|
|
<pre><code>#axiom
|
|
B(1)
|
|
#rules
|
|
B(a) : a<2 -> B(a+0.1)
|
|
B(a) : a>=2 -> B(1)B(1)
|
|
#end rules</code></pre>
|
|
<p>Parametry zapisuje się wewnątrz nawiasów po przecinku. W aksjomacie muszą one mieć wartości liczbowe. Po lewej stronie trzeba nadać parametrom nazwy (mogą mieć one więcej niż jeden znak). Symbole są identyfikowane po nazwie i liczbie znaków. Po dwukropku można podać warunki logiczne jakie musi spełnić symbol. można w tym umieszczać operacje matematyczne, dozwolone jest mnożenie, dzielenie, dodawanie i odejmowanie. podobnie w parametrach po prawej stronie</p>
|
|
<h3 id="zadanie-3">Zadanie</h3>
|
|
<p>Napisz dla parametrycznej wersji Anabeny taką interpretację, żeby komórki rosły wraz z wiekiem.</p>
|
|
<h2 id="stochastyczne-l-systemy">Stochastyczne L-Systemy</h2>
|
|
<p>Niektóre procesy biologiczne są zbyt skomplikowane albo niedostatecznie zbadane, żeby można je było je zasymulować lub zwyczajnie nie mamy potrzeby symulować mechanizmów tak dokładnie. Zamiast tego możemy skorzystać z losowości, która przybliży zachowanie natury.</p>
|
|
<p>Przykładowo możemy losowo decydować czy w roślinie wyrośnie boczna gałąź czy nie. Co realizuje poniższy L-System (znajduje się on także w pliku <code>stochastic.txt</code>)</p>
|
|
<pre><code>#axiom
|
|
B
|
|
#rules
|
|
B -> #stochastic
|
|
p=3 FB
|
|
p=1 [+FB]FB
|
|
p=1 [-FB]FB
|
|
p=1 F
|
|
#stochastic end
|
|
#rules end
|
|
</code></pre>
|
|
<p>W powyższym przypadku mamy symbol B, który symbolizuje merystem (część rośliny zdolną do rozwoju); F oznacza rozwiniętą gałąź. B może rozwinąć łodygę, wytworzyć gałąź po prawej, wytworzyć gałąź po lewej lub zaprzestać rozwój.</p>
|
|
<p>Odpal scenę <code>LSystem2D</code> załaduj <code>stochastic.txt</code> i odpal kilka razy od początku (żeby zresetować, kliknij <em>Load File</em>).</p>
|
|
<p>Reguły stochastyczne należy zacząć od słowa <code>#stochastic</code>. Następnie po linijce wypisać wyniki, poprzedzając je frazą <code>p=W</code>, gdzie <code>W</code> to waga danego wyniku. Wagi mogą być dowolną dodatnią liczbą rzeczywistą. Interpreter na podstawie wag przydzieli prawdopodobieństwo kolejnym wynikom. Przykładowo w powyższym L-Systemie reguły zostaną wykonane następująco:</p>
|
|
<ul>
|
|
<li>FB z prawdopodobieństwem <span class="math inline">\(\frac{3}{6}\)</span></li>
|
|
<li>[+FB]FB z prawdopodobieństwem <span class="math inline">\(\frac{1}{6}\)</span></li>
|
|
<li>[+FB]FB z prawdopodobieństwem <span class="math inline">\(\frac{1}{6}\)</span></li>
|
|
<li>F z prawdopodobieństwem <span class="math inline">\(\frac{1}{6}\)</span></li>
|
|
</ul>
|
|
<p><img src="Screenshot 2021-03-14 at 07.32.36.png" alt="Screenshot 2021-03-14 at 07.32.36" style="zoom:33%;" /><img src="Screenshot 2021-03-14 at 07.32.56.png" alt="Screenshot 2021-03-14 at 07.32.56" style="zoom:33%;" /> <img src="Screenshot 2021-03-14 at 07.33.17.png" alt="Screenshot 2021-03-14 at 07.33.17" style="zoom:33%;" /></p>
|
|
<h3 id="zadanie-4">zadanie</h3>
|
|
<p>Obecnie zdarza się tak, że L-System wchodzi w ostatnią regułę na samym początku i nic nie wyrasta. Innym razem wyrasta bardzo dużo odgałęzień i całość wymyka się spod kontroli a na pewno przestaje przypominać roślinę. Pomyśl jak można zaradzić tym dwóm problemom, zmodyfikuj L-System tak, by ich uniknąć. Możesz dodać nowe symbole lub/i wykorzystać symbole parametryczne.</p>
|
|
<h2 id="zadanie-domowe">Zadanie domowe</h2>
|
|
<p>Scena <code>LSystem3D</code> jest kopią sceny <code>LSystem2D</code>, korzysta ona ze skryptu <code>Turtle3D</code> zamiast <code>Turtle2D</code> (chociaż są one na razie identyczne). Dodaj do <code>Turtle3D</code> obsługę obrotów w trzech wymiarach za pomocą znaków:</p>
|
|
<ul>
|
|
<li><code>&</code> obrót do góry (pitch), czyli obrót względem osi X o kąt <span class="math inline">\(\delta\)</span></li>
|
|
<li><code>^</code> obrót do góry (pitch), czyli obrót względem osi X o kąt <span class="math inline">\(-\delta\)</span></li>
|
|
<li><code>\</code> obrót do obrót w prawo (roll), czyli obrót względem osi Y o kąt <span class="math inline">\(-\delta\)</span></li>
|
|
<li><code>/</code> obrót do obrót w lewo (roll), czyli obrót względem osi Y o kąt <span class="math inline">\(\delta\)</span></li>
|
|
</ul>
|
|
<p>Poza tym dla symboli <code>L</code> i <code>F</code> dodaj interpretacje kolejno jako liść i kwiat. W folderze Models są gotowe modele, ale możesz ściągnąć własne.</p>
|
|
<p>Wykorzystaj dotychczasową wiedzę i powyższą interpretację, by stworzyć L-System generujący roślinę polną jak poniższy chaber.</p>
|
|
<figure>
|
|
<img src="7_Centaurea_cyanus.jpg" alt="rysunek chabra z wikipedii" /><figcaption aria-hidden="true">rysunek chabra z wikipedii</figcaption>
|
|
</figure>
|
|
</body>
|
|
</html>
|