Hogyan forgassunk el egy adott pontot adott szöggel, adott forgáspont körül?

Grafikus alkalmazásoknál alapvető funkció egy pont adott szöggel való elforgatása, az origó vagy egy megadott forgáspont körül. A forgatás megvalósítását egy olyan függvénnyel oldhatjuk meg, amelynek argumentumai a forgatandó pont, a forgáspont és az elforgatás szöge, visszatérési értéke pedig az elforgatott pont.

A kérdés, hogy a függvény törzsében milyen képletet megvalósító kód kerül. Ennek megválaszolásához némi matematikai ismeret szükséges. Általában a vektor-, illetve koordinátageometrián alapuló levezetés a szokásos, amelyből kiadódnak a forgatott pont koordinátáit meghatározó egyenletek, vagy ha mátrixalgebrai alakban írjuk ezeket fel, akkor megkapjuk a forgatási mátrixot. Ezek levezetése látható alább vektorábrával szemléltetve a forgatási eseteket.

Más módon is meghatározhatjuk a forgatott pontot, mégpedig a koordinátageometriával szoros kapcsolatba hozható komplex számokkal. Ennek levezetése a következő:

Itt két végképletet is láthatunk attól függően, hogy a képletben szereplő forgatási tényezőt exponenciális alakban, vagy trigonometrikus alakban fejezzük ki. Bár matematikailag ezek ekvivalensek, de kódolás szempontjából van különbség, mert míg az előbbihez a Python szabványos könyvtárából a cmath modul szükséges, addig az utóbbihoz a math modul.

A fentiek alapján tehát három különböző logikára, illetve képletre épülő függvényt tudunk definiálni a forgatott pont meghatározására. Ezek definícióit láthatjuk alább, ahol az egyes függvények törzsében szereplő kódok követik a levezetésekben kapott képleteket, ezért a működés bővebb magyarázatot nem igényel.

A tényleges pontforgatás elvégzésére egy külön objektumot hozunk létre, amelynek Rotator nevű osztályának definíciója szintén az előbbi kódban látható. Ennek az az értelme, hogy a három, forgatott pontot meghatározó függvény közül bármelyiket alkalmazhatjuk, akár futási időben váltakozva úgy, hogy a kliens kódot ez nem érinti, mert ott mindig ugyanazt a nevű metódust kell meghívni. Ez a kialakítás a stratégia tervezési mintát (strategy design pattern) követi annyiban eltérve a klasszikus felépítéstől, hogy kihasználjuk azt, hogy a Pythonban a függvények objektumok, ami lehetővé teszi, hogy argumentumként átadhatók legyenek. Így az eredeti klasszikus stratégia mintában szereplő, az egyes algoritmusokra, stratégiákra vonatkozó osztályok létrehozása nem szükséges.

A következő néhány tesztesetben különböző megvalósítású forgatási algoritmusokkal használjuk a Rotator példányt. Nem meglepő módon mindegyik azonos eredményt produkál.

E bejegyzés témájához a Python tudásépítés lépésről lépésre című e-könyv következő részei kapcsolódnak: az „Egymáshoz rendelve – függvények” fejezet „A függvény is objektum” alfejezete, valamint a „Készétel fogyasztás – a szabványos könyvtár moduljainak használata” fejezetben a „Speciális konténer típusok” alfejezet „Mezőneves tuple – namedtuple” cím, továbbá a „Matematikai számítások támogatása” című alfejezet „Valós és komplex változós függvények” címe, amelyben a math és cmath modulok leírása és alkalmazása olvasható.

Érdekel a Python tudásépítés lépésről lépésre az alapoktól az első asztali alkalmazásig című e-könyv.