Sokszögek területszámítása témában legtöbbször szabályos sokszögek területének meghatározásával találkozhatunk. A nem szabályos sokszögek területének kiszámítására pedig többnyire annyi az utalás, hogy háromszögekre kell bontani, majd az egyes háromszögek területét kiszámolni például a Heron képlettel és ezeket összeadni. (A Heron képlet számítási pontosságkorlátairól lásd a „Tűszerű háromszögek területének számítása” című bejegyzést)
E módszer lerajzolt sokszögeknél jól használható, mert vizuálisan átlátjuk a rajzot és így azt könnyen fel tudjuk a megfelelő háromszögekre bontani akár konvex, akár konkáv sokszögről van szó. De mi van akkor, ha nem áll rendelkezésre rajz, és a sokszög csúcspontjainak koordinátáival van meghatározva?
Ekkor a háromszögek meghatározása nem egy magától értetődő könnyű feladat, különösen konkáv sokszög esetében. Ezért e helyett inkább egy speciális módon történő trapézokra bontás, és azok előjeles területének meghatározása majd összegzése az alkalmazott módszer.
Ennek lényege, hogy a csúcspontokat az oldalak mentén sorban egymás után bejárjuk, és ennek során mindig vesszük az aktuális pontot és a rákövetkező pontot. Ezeket felhasználva képezünk egy olyan trapézt, amelynek alapjai a pontok y koordinátái, magassága az x koordináták különbsége. Ezek ismeretében kiszámítjuk a trapéz területét, ami, mint azt az elemi geometriából tudjuk, az alapok számtani közepe szorozva a magassággal. Fontos, hogy a magasságot mindig úgy határozzuk meg, hogy a rákövetkező pont x koordinátájából vonjuk ki az aktuális pont x koordinátáját. Ez azért lényeges, mert a pontok bejárása során lesznek olyan esetek, amikor a rákövetkező pont x koordinátája kisebb az aktuális pont x koordinátájánál, vagyis a kialakuló trapéz területe negatív lesz. A sokszög területét a pozitív és negatív területek összege adja. A módszert a következő ábra szemlélteti.

A képsorozaton egy konkáv hétszög területének fokozatos „lefedését” látjuk ahogy a csúcspontokon végighaladunk az oldalak mentén. A kék és fehér színű trapézok területének összege adja ki a hétszög területét minthogy a csúcspontok óramutató járásával egyező bejárási sorrendjét betartva a kék színű trapézok növelik a lefedett területet, a fehérek csökkentik. Fordított bejárási sorrend esetén a negatív értékű trapézok területe lenne több, és az összegzés végeredménye negatív érték lenne. Ezért az összegzés után az eredmény abszolút értékét kell venni.
A számítási elv ismeretében a sokszögterületet számoló függvény elég egyszerű lesz. Sorban egymás után kell venni a szomszédos csúcspárokat és azok koordinátáiból képezni az egyes trapézok területét, amelyeket egy listaépítő kifejezéssel gyűjtünk. Ha a lista előállt, akkor az elemeket a sum() függvénnyel összegezzük, és az eredmény abszolút értékével térünk vissza. A csúcspontok sorozatából a szomszédos párokat az itertools modul pairwise() iterátorával nyerjük ki. Mivel az utolsó csúcspont és az első csúcspont által meghatározott trapézt, illetve annak területét is elő kell állítani, ezért a pairwise() argumentumaként nem elegendő csak a csúcspontsorozatot megadni, hanem a sorozat utolsó elemeként az első csúcspontot is fel kell venni. Ezt az összefűzést az itertools modul chain() iterátorával tesszük meg. Az ennek megfelelő függvény definíciója az alábbi:
|
1 2 3 4 5 6 7 8 9 10 11 |
# Python 3.10+ from itertools import pairwise, chain import tkinter as tk def polygon_area(polygon_vertices): trapezoid_signed_areas = [(x2 - x1) * (y2 + y1) for (x1, y1), (x2, y2) in pairwise(chain(polygon_vertices, [polygon_vertices[0]]))] return 0.5 * abs(sum(trapezoid_signed_areas)) |
Teszteljük le a függvényt! Ehhez különböző sokszögeket határozunk meg csúcspontjaikkal. Utána ezeket ki is rajzoljuk, és mindegyik alatt feltüntetjük a területszámoló függvénnyel meghatározott területet. A tesztkód az alábbi:
|
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 |
# TESZT # Sokszögek csúcspontokkal megadva. vertices1 = [(20, 20), (20, 180), (100, 20)] vertices2 = [(20, 20), (20, 180), (100, 180), (100, 20)] vertices3 = [(20, 20), (20, 180), (100, 180), (140, 100), (100, 20)] vertices4 = [(20, 20), (60, 120), (20, 180), (100, 180), (140, 100), (100, 20)] vertices5 = [(20, 20), (60, 120), (20, 180), (100, 180), (140, 100), (80, 60), (100, 20)] root = tk.Tk() root.geometry('900x250') root.title('Sokszögek területe') cnv = tk.Canvas(root, bg='light yellow') cnv.pack(fill=tk.BOTH, expand=True) colors = ('silver', 'gold', 'cyan', 'green', 'red') dx, dy = 0, 0 for vertices, fill_color in zip((vertices1, vertices2, vertices3, vertices4, vertices5), colors): shape_id = cnv.create_polygon(vertices, fill=fill_color, outline='black', width=3) cnv.move(shape_id, dx, dy) x1, y1, x2, y2 = cnv.bbox(shape_id) cnv.create_text((x1 + x2) / 2, y2 + 20, text='{:g}'.format(polygon_area(vertices)), font=('Consolas', 14, 'bold')) dx += 180 root.mainloop() |
Az eredményként látható képernyőkép a következő:

E bejegyzésben az itertools modul eszköztárát tudtuk hatékonyan alkalmazni. Az e modulban található egyéb iterátorokról alkalmazási példákkal együtt a Python tudásépítés lépésről lépésre című e-könyv „Készétel fogyasztás – a szabványos könyvtár moduljainak használata” fejezetén belül a „Speciális iterátorok” alfejezetben lehet olvasni.