Az előző bejegyzésben egy adott pont megadott szöggel történő elforgatásával kapott pont meghatározásával foglalkoztunk, és erre három különböző számítási módszert alkalmazó függvényt definiáltunk. Most egy adott pont tengelyes tükrözéseképpen előálló pont meghatározása lesz a cél.
Ahogy a forgatásnál tettük most is két megközelítést alkalmazunk a tükörpont származtatására. Az egyik a koordinátageometriai. Ekkor eltolás, forgatás és újabb eltolás geometriai transzformációk sorozatával oldjuk meg a feladatot. Ezt láthatjuk alább vektorábrával szemléltetve, és alatta a lépéseket részletesen kifejtve.

Láthatjuk, hogy a forgatás műveletét is használtuk, tehát most nyert értelmet, hogy miért foglalkoztunk előzőleg a forgatással.
A tengelyesen tükrözött pont meghatározása komplex számok segítségével is lehetséges. Ennek levezetése:

E megoldásban az előzőhöz képest az előny, hogy nem kell használnunk se forgatást végző függvényt, se trigonometrikus függvényt, hanem csak a komplex számok alapműveleteit.
Mindenesetre két számítási módszer áll rendelkezésünkre, amelyek alapján egy-egy függvényt definiáltunk az alább látható módon. A vektorábra és a levezetések ismeretében ezek működése nem szorul részletesebb magyarázatra. A Pont típust, valamint a tükrözést koordinátageometriai módszerrel megoldó függvény működéséhez a forgatást végző függvényt az előző bejegyzésben szereplő definíciókból vesszük; erre utal az elején az import sor, ahol a point_rotation modul rotate_point függvénye bármelyik forgató függvény lehet az előző bejegyzésben definiáltakból.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
from point_rotation import Point, rotate_point from math import atan2 def reflect_about_line_geom(point: Point, p1: Point, p2: Point): """A megadott point pontnak a p1 és p2 pontok által meghatározott tengelyre vett tükörkép pontjával tér vissza. A tükörpont meghatározása eltolás, forgatás és visszatolás geometrikai transzformációkkal valósul meg. """ # Azzal a vektorral toljuk el a pontot, amellyel a szakaszt kelle, hogy a kezdete az origóba kerüljön. ps = Point(point.x - p1.x, point.y - p1.y) # Az eltolt pontot tükrözzük az x tengelyre. psi = Point(ps.x, -ps.y) # Elforgatjuk 2alpha szöggel. alpha = atan2(p2.y - p1.y, p2.x - p1.x) psir = rotate_point(psi, Point(0, 0), 2 * alpha) # Visszatoljuk a pontot. p_reflected = Point(psir.x + p1.x, psir.y + p1.y) return p_reflected def reflect_about_line_complex(point: Point, p1: Point, p2: Point): """A megadott point pontnak a p1 és p2 pontok által meghatározott tengelyre vett tükörkép pontjával tér vissza. A tükörpont meghatározása komplex számokkal való műveletekkel valósul meg. """ pc, p1c, p2c = complex(*point), complex(*p1), complex(*p2) ps = pc - p1c psi = ps.conjugate() psir = psi * (p2c - p1c) / (p2c - p1c).conjugate() p_reflected = psir + p1c return Point(p_reflected.real, p_reflected.imag) class PointReflector: def __init__(self, reflection_strategy=reflect_about_line_complex): self.reflection_strategy = reflection_strategy def reflect_about_line(self, point_to_reflect: Point, line_start_point: Point, line_end_point: Point): return self.reflection_strategy(point_to_reflect, line_start_point, line_end_point) def set_reflection_strategy(self, reflection_strategy): self.reflection_strategy = reflection_strategy |
Mivel két módszerünk is van, ezért ahogy a forgatásnál tettük, most is definiáltunk egy olyan objektumot PointReflector néven, amelyben a tükrözési algoritmust akár futási időben tudjuk változtatni. /Tehát, ahogy a forgatásnál, ebben az esetben is a stratégia tervezési mintát valósítottuk meg/
Azt, hogy a két, tengelyes tükrözést végző függvény helyesen működik és azonos eredményt ad, a következő néhány tesztsor eredménye igazolja:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# TESZT # A tükrözési tesztadatok listája a tükrözendő pont és a tengely két pontjának megadásával reflection_data = [(Point(1, 1), Point(2, 2), Point(3, 3)), (Point(1, 2), Point(2, 2), Point(3, 3)), (Point(1, 2), Point(2, 1), Point(4, 3)), (Point(4, 1), Point(1, 3), Point(5, 2))] # A tükrözést végző objektum létrehozása. point_reflector = PointReflector() for reflection_strategy in (reflect_about_line_geom, reflect_about_line_complex): # A tükröző objektumban a tengelyes tükrözést megvalósító algorimus beállítása. point_reflector.set_reflection_strategy(reflection_strategy) print('\n{}'.format(reflection_strategy.__name__)) # Az adott tesztadatokkal a tükrözés végrehajtása, majd a tengelyt meghatározó pontok, valamint a # tükrözendő pont és tükörképének kiírása. for args in reflection_data: print('Tengely: {0[1]} -- {0[2]}\n\t{0[0]} -> {1}'.format(args, point_reflector.reflect_about_line(*args))) # Eredmények: # reflect_about_line_geom # Tengely: Point(x=2, y=2) -- Point(x=3, y=3) # Point(x=1, y=1) -> Point(x=1.0, y=1.0) # Tengely: Point(x=2, y=2) -- Point(x=3, y=3) # Point(x=1, y=2) -> Point(x=2.0, y=1.0) # Tengely: Point(x=2, y=1) -- Point(x=4, y=3) # Point(x=1, y=2) -> Point(x=3.0, y=0.0) # Tengely: Point(x=1, y=3) -- Point(x=5, y=2) # Point(x=4, y=1) -> Point(x=4.588235294117647, y=3.3529411764705883) # # reflect_about_line_complex # Tengely: Point(x=2, y=2) -- Point(x=3, y=3) # Point(x=1, y=1) -> Point(x=1.0, y=1.0) # Tengely: Point(x=2, y=2) -- Point(x=3, y=3) # Point(x=1, y=2) -> Point(x=2.0, y=1.0) # Tengely: Point(x=2, y=1) -- Point(x=4, y=3) # Point(x=1, y=2) -> Point(x=3.0, y=0.0) # Tengely: Point(x=1, y=3) -- Point(x=5, y=2) # Point(x=4, y=1) -> Point(x=4.588235294117647, y=3.3529411764705883) |
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 „Beépített típusok nyilvános metódusai” fejezetben a format() függvény használata, továbbá 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, 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 modulok leírása és alkalmazása olvasható.