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]:

Subdivision-görbe

Áttekintés

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:

Elvárt jellemzők

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

  • megjeleníti az eredeti (azaz a 0. iterációhoz tartozó) kontrollpontokat,
  • mindig megjeleníti az eredeti (azaz a 0. iterációhoz tartozó) kontrollpoligont,
  • megjeleníti az 1-2-3-4. iterációkhoz tartozó kontrollpoligonokat,
  • lehetővé teszi külön-külön az 1-2-3-4. iterációkhozhoz tartozó kontrollpoligonok megjelenítésének kikapcsolását,
  • tetszőleges számú kontrollpont elhelyezését teszi lehetővé,
  • már elhelyezett kontrollpont mozgatását lehetővé teszi (például drag & drop módszer segítségével),
  • lehetővé teszi a feszességi érték (tension) megváltoztatását,
  • által kirajzolt görbe minden iterációja valós időben követi a kontrollpontok mozgását, azaz a görbe megváltozása nem csak akkor lesz látható, amikor egy kontrollpont vonszolását befejeztük, hanem a vonszolás közben végig,
  • lehetővé teszi az összes elhelyezett kontrollpont egyidejű törlését,
  • megjelenít egy rácsot, ami megkönnyíti a kontrollpontok elhelyezését,
  • a görbepontok kiszámításához a kiírás további részében leírt módszert használja.

A görbét csak a negyedik kontrollpont elhelyezése után kell elkezdeni kirajzolni.

A használt séma

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[ $$

Egy finomítás kiszámítása

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.

Demonstráció

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]: