In [1]:
from IPython.core.display import HTML
from string import Template
def jsConfig():
src = """
<script>require.config({ baseUrl: 'https://rawgit.com/kompgraf/course-material/master/assets/' });</script>
"""
return HTML(src)
def addScript(script, identifier):
src = Template("""
<div id="${identifier}-container"></div>
<script>require(['${script}'], main => main($$("#${identifier}-container"), '${identifier}'));</script>
""")
return HTML(src.substitute(script = script, identifier = identifier))
jsConfig()
Out[1]:
A feladat egy zárt subdivision-görbe kirajzolására képes program elkészítése, mely a görbe pontjait a Beccari és munkatársai által kidolgozott interpolating 4-point $C^2$ non-stationary ternary séma segítségével számolja ki. Az eredeti cikk elérhető a következő címen:
A házi feladat megvédése csak akkor lehet sikeres, ha a program a jellemzőit tekintve hiánytalan. Az elvárt jellemzőket teljesítő program
A görbét csak a negyedik kontrollpont elhelyezése után kell elkezdeni kirajzolni.
Vegyük először sorra, hogy a módszer neve milyen jellemzőket árul el a finomításokat alkotó számításokról! A séma 4-point, azaz a soron következő finomítás egy új kontrollpontjának meghatározásához legfeljebb 4 régit fogunk felhasználni. Ezen felül ternary, tehát az új kontrollpontokat három különböző szabály alkalmazásával tudjuk majd számolni. Végül, tekintve, hogy interpolatory tulajdonságú eljárást alkalmazunk, az előző kontrollpoligon minden pontját át fogjuk vinni az új kontrollpoligonba is.
A pontos képletek a következőek:
$$ \begin{align*} P^k_{3j} &=P^{k-1}_j \\ P^k_{3j + 1} &= \alpha^{k-1}_{0}P^{k-1}_{j - 1} + \alpha^{k-1}_{1}P^{k-1}_{j} + \alpha^{k-1}_{2}P^{k-1}_{j + 1} + \alpha^{k-1}_{3}P^{k-1}_{j + 2} \\ P^k_{3j + 2} &= \alpha^{k-1}_{3}P^{k-1}_{j - 1} + \alpha^{k-1}_{2}P^{k-1}_{j} + \alpha^{k-1}_{1}P^{k-1}_{j + 1} + \alpha^{k-1}_{0}P^{k-1}_{j + 2} \end{align*} $$Tehát minden finomítás során megtartjuk az előző kontrollpoligon pontjait, és minden négy egymást követő pont kétféle lineáris kombinációját képezzük az $\alpha^{k-1}_i$ $(i = 0, 1, 2, 3)$ értékek segítségével. Ezeket az együtthatókat a következő módon számolhatjuk:
$$ \begin{align*} \alpha^{k}_0 &= \frac{1}{60}(-90\gamma^{k + 1} - 1) \\ \alpha^{k}_1 &= \frac{1}{60}(90\gamma^{k + 1} + 43) \\ \alpha^{k}_2 &= \frac{1}{60}(90\gamma^{k + 1} + 17) \\ \alpha^{k}_3 &= \frac{1}{60}(-90\gamma^{k + 1} + 1) \\ \end{align*} $$Ahol
$$ \gamma^{k + 1} = - \frac{1}{3(1 - (\beta^{k + 1})^2)(1 + \beta^{k + 1})}, $$és
$$ \beta^{k + 1} = \sqrt{2 + \beta^{k}} \qquad \beta^{k} \in [-2, \infty[ \; \setminus \, \{ -1 \} \quad \forall k \in [0, 1, \ldots, \infty[ $$Kezdetben tehát adott a $P^0$ kontrollpoligon, melynek pontjait a felhasználó helyezte el, valamint egy $\beta^0$ feszességi érték, amely egy olyan valós szám, ami $-2$ és pozitív végtelen között vehet fel értékeket, a $-1$ kivételével.
Kiindulva egy tetszőleges kontrollpoligonból (azaz $k \geq 0$ tetszőleges egész), először meghatározzuk a következő $\beta^{k + 1}$ feszességi paramétert. Ezt folytatjuk a $\gamma^{k + 1}$, majd az $\alpha^{k}_i$ értékek kiszámításával.
Miután az együtthatókat meghatároztuk, rátérünk a tényleges subdivisionre. Mivel zárt görbét készítünk, vesszük a $k$-adik iteráció minden kontrollpontját. Az összes kontrollpont esetén vesszük azok megelőzőjét és két rákövetkezőjét. Az így kapott négyesekre már alkalmazhatjuk az előbb felírt képleteket. A négyesekből képzett új kontrollpont-hármasokat sorrendben összefűzve kapjuk az új, finomított kontrollpoligont. Az eljárást addig ismételjük, míg kellően sima görbét nem kapunk.
A házi feladat részeként $4$ egymást követő finomítást kell kiszámolni.
A demonstráció kezelése a megszokott módon történik. A feszességet a Tension mező értékének módosításával befolyásolhatjuk; $\beta^0 = -1$ esetén a görbe egyszerűen eltűnik.
A házi feladat alapját képező séma szabályos sokszögek esetén adja a legérdekesebb eredményeket, emiatt szükséges a rács megjelenítése, a kontrollpontok megfelelő elhelyezését elősegítendő.
In [3]:
addScript("js/four-point-subdivision", "four-point-subdivision")
Out[3]:
In [2]:
def styling():
styles = open("../../styles/custom.html", "r").read()
return HTML(styles)
styling()
Out[2]: