Naprendszer szimuláció – megvalósítás Java nyelven

Naprendszer szimulációt terveztünk és valósítottunk meg Java nyelven, amit három részből álló blog bejegyzés sorozatban mutatunk be (ez a 3. rész):

A Naprendszer szimuláció megvalósítása Java nyelven

Fejlesztőeszközként a Java Swinges projekthez a JDK+JRE aktuális verziót támogató NetBeans IDE-t használtuk. Hibakeresés során, a modell adatainak ellenőrzését és a működés helyességének egyszerű tesztelését, debuggolást konzolra történő szöveges kiírással oldottuk meg. A megvalósítás során az előre megtervezett osztálydiagramok alapján készült el Java nyelven a forráskód. Az MVC modell szerint elkülönített programrészek külön csomagokba kerültek, ezzel is kiemelve a funkciók szerinti szétválasztást – eleget téve a terv követelményeinek.

Részlet a Java forráskódból

Megmutatjuk a Java forráskódnak azt a részét, ami megvalósítja az elméleti háttérnél ismertetett transzformációs mátrix alkalmazását X tengely körüli elforgatásra, a nézőponttól való távolság függvényében az égitest látható méretének kiszámítását, valamint a 3D→2D leképezést.

A teljes és megjegyzésekkel ellátott forráskód ILIAS e-learning tananyagban hozzáférhető, letölthető, tesztelhető tanfolyamaink résztvevői számára.

Az elkészült Java Swinges alkalmazás felhasználói felülete

Tapasztalatok

  • A Java nyelv erősen típusos, így a kötelező és sok lebegőpontos/egész átalakítás miatt észrevehető, hogy a legkisebb égitest (Hold) kissé ugrál.
  • Az OO szempontból szép Java megvalósítás könnyen módosítható és bővíthető, a funkciók jól csoportosítottak, a felelősségi kör egyértelműen meghatározott.
  • A projekt megtervezéséhez és elkészítéséhez magasabb szintű absztrakciós készség szükséges.
  • A példaprogram alkalmas a különböző szakterületek, témakörök (matematika – lineáris algebra, fizika, számítógépes grafika, virtuális valóság modellezése) közötti kapcsolatok felismertetésére, megerősítésére, a (legalább részben) egymásra épülések felderítésére.
  • A ter­v átgondolásával, implementálásával gyors, látványos eredmény érhető el, a sikerélmény hamar jelentkezik.

Továbbfejlesztési lehetőségek

  • Célszerű ötlet a hardveres gyorsítás és 3D megjelenítés megvalósítása.
  • Felkínálható lenne a felhasználó számára több paraméter módosítása.
  • Az égitestek lehetnének textúrázhatók is.
  • Az égitestek pozíciója kiinduló helyzetben lehetne valós.
  • A szimuláció szükség esetén lehetne elindítható, leállítható, újraindítható, gyorsítható, lassítható.
  • A terv könnyen implementálható lehet Java3D techno­lógia alkalmazásával, illetve DirectX és/vagy OpenGL támogatással is.
  • Az égitestek pozíciója és mozgása demonstrálhatna/modellezhetne nevezetes együttállást is, külön esettanulmányként.
  • A program paraméterezhető lehetne konfigurációs fájlból (amelynek formátuma tetszőleges: INI, XML).
  • Fejlettebb matematikai modell is alkalmazható lenne.

Forrás

  • Friedel, A.; Kaczur, S. (előadó: Friedel, A.): Naprendszer szimuláció a Virtuális valóság modellezése tantárgyban, Informatika Korszerű Technikái Konferencia, Dunaújváros, Dunaújvárosi Főiskola, 2012. november 16-17. (előadás hazai konferencián)
  • Friedel, A.; Kaczur, S.: Naprendszer szimuláció a Virtuális valóság modellezése tantárgyban, Cserny, L.; Hadaricsné Dudás, N.; Nagy, B. (szerk): Dunakavics Könyvek 2. – Az Informatika Korszerű Technikái, Dunaújvárosi Főiskola, Új Mandátum Könyvkiadó, 2014, ISBN 978 963 287 069 4, ISSN 2064-3837, p. 72-84 (magyar nyelvű szakcikk)

Naprendszer szimuláció – objektumorientált tervezés

Naprendszer szimulációt terveztünk és valósítottunk meg Java nyelven, amit három részből álló blog bejegyzés sorozatban mutatunk be (ez a 2. rész):

A Naprendszer szimuláció objektumorientált tervezése

A Naprendszer égitestjeinek ábrázolása a valódi világban előforduló méretük és távolságuk szerint történik azért, hogy a szimuláció stabil legyen. A példában a Nap és a három belső bolygó szerepel, valamint a Hold. Utóbbi igazolja, hogy nem csak Nap középpontú égitestekre működőképes a modell. A szimuláció diszkrét lépések véges sorozataként valósul meg, az egyes lépések között az égitestek a virtuális térben egyenes vonalú egyenletes mozgást végeznek. Olyan lépésközt kell választani, amely rövid idő alatt kellően nagy változást képes bemutatni, ilyen például az 1 számítási ciklus / 1 nap érték. 10 képkocka / másodperces megjelenítést feltételezve – melyet egy időzítő biztosít – egy virtuális év kb. 37 másodperc alatt telik el, vagyis a Föld ennyi idő alatt tesz meg egy teljes fordulatot a Nap körül. Az égitestek kezdő pozíciója fiktív, nem függ konkrét dátumtól, együttállástól, méretük a jobb láthatóság érdekében torzított.

A program indításakor a szimuláció automatikusan indul, és nincs lehetőség a leállításra. Az alkalmazás felületének tetején foglalnak helyet a kezelő nyomógombok, a többi részt a megjelenítés/transzformált modelltér tölti ki. Futás közben – egyszerű ese­mény­ke­zelést megvalósítva – lehet változtatni a méretarányt és a nézőpontot, így az ekliptika síkját felülről és elbillentve is ábrázolhatjuk.

Kivételkezelés nem szükséges a programhoz, mert ez egy önálló demonstrációs eszköz, nem épül rá több elem, nem érhetőek el a szolgáltatásai külső programok számára.

Meghatározott cél és a szempontok: a Java projektben a csomagokat az MVC szerint hozzuk létre, a funkciókat logikusan osszuk szét, csoportosítsuk, tartsuk be az objektumorientált szemléletmód elveit, használjunk interfészt, biztosítsuk az egység­bezárást, legyen öröklődés, alkalmazzuk a polimorfizmust, legyen szép és elegáns megoldás, legyen a jelölésrendszer UML osztálydiagram. Mindez grafikus asztali Java alkalmazásként valósuljon meg.

A modell csomag (M – Model)

A modellhez 1 interfész és 5 osztály tartozik:


Az AdatInterfesz tárolja a modell számításhoz és megjelenítéshez tartozó konstansait (ezek a szimuláció paraméterei), és metódusfejet nem tartalmaz. A Pont2D osztály egy kétdimenziós pont sémája, valós x és y koordinátapárral, eltol() és túlterhelt tavolsag() metódusokkal. Ennek leszármazottja a Pont3D osztály, amely mindezt három dimenzióban biztosítja, valamint pozícióként és sebességvektorként is használható. Az Egitest osztályból létrehozott objektumnak van mérete, pozíciója, sebessége, színe és tömege. Az interfészt implementálja az Adattar osztály, amelynek egitestLista nevű generikus listája elérhetővé és egységesen kezel­hetővé teszi a tervben felsorolt 5 égitestet. A ZIndex osztályú objektumok az égitestek kirajzolásakor szükséges mélységpufferbeli adatot képesek kezelni.

A nézet csomag (V – View)

A nézet 2 osztályból áll:


Az Ablak osztály egy javax.swing.JFrame le­szár­mazott, az alkalmazás teljes grafikus felületét biztosítja, valamint előkészíti az eseménykezelést. Tartalompanelje négy vezérlő nyomógombot tartalmaz és rajta található a rajzpanel objektum, a vaszon. A RajzPanel osztály egy javax.swing.JPanel leszármazott, amely kapcsolatban áll az adattárral, és kezeli a mélységpuffert. Ez felel a szimulált 3D térben lévő objektumok 2D-beli leképezéséért, figyelembe véve a nézőpont elmozdulását is. A rajzolást a felüldefiniált (öröklődés) paintComponent() metódus végzi el.

Az Ablak osztályú objektum elsődleges szerepet tölt be a megjelenítésben, keretbe foglalva a látható komponenseket, vagyis a kezelő nyomógombokat és a modellteret. Az objektum megvalósít egy ActionListener eseménykezelőt, így a program reagálni tud a felhasználó által kiváltott eseményekre. Az ablakobjektum nagyítás és forgatás üzenetek küldésével saját vásznát – és csak azt – frissíti.

A vezérlő csomag (C – Controller)

A vezérlőt 2 osztály valósítja meg:

A Main osztály összefogja a projektet, ez a végrehajtás belépési pontja. Szükség szerint átadja az MVC szerinti objektumok referenciáit egymásnak, ezzel biztosítva a kommunikációt közöttük, valamint el is indítja a szimulációt. A Logika osztály képes az égitestek gyorsulásának és vonzásának kiszámítására, az égitestek mozgatására, továbbá a megjelenítésért felelős komponenst megfelelő időközönként értesíti a képernyő frissítésének szükségességéről, ami az alapbeállítás szerint 30 frissítés másod­percenként.

Naprendszer szimuláció – elméleti háttér

Naprendszer szimulációt terveztünk és valósítottunk meg Java nyelven, amit három részből álló blog bejegyzés sorozatban mutatunk be (ez az 1. rész):

A Naprendszer szimuláció elméleti háttere

A Naprendszer szimulációhoz elengedhetetlen, hogy ismerjük a homogén koordinátákat, az elemi műveletek egységes megvalósításához szükséges transzformációs mátrixokat, a tömegvonzás elvét és az implementációhoz szükséges MVC modellt.

Homogén koordináták

Számítógépes algoritmusokkal egyszerű a térbeli transzformáció megvalósítása, ha homogén koordinátákat használunk. Segítségükkel az affin transzformációk egységesen kezelhetők. A cél egy egységes matematikai formalizmus alkalmazása. A pontok az égitestek középpontjait fogják jelölni. Legyen a P pont 3D-beli koordinátái: P=(x, y, z). Szükséges egy konstans érték. Ha w≠0, akkor a P pont koordinátái: P=(w·x, w·y, w·z, w). Ha w=1, akkor a P pont normalizált homogén koordinátái: P=(x, y, z, 1). A pontnégyes kijelölése kölcsönösen egyértelmű.

Transzformációk

Koordináta transzformáció során az ábrázolandó grafikus objektum pontjaihoz (tárgypontokhoz) új koordináta-rendszert rendelünk hozzá. Az objektum nem változik (nem torzul, nem változtatja meg az alakját), csupán a nézőpont változik meg. Például: a koordináta-rendszer eltolása, elforgatása, a koordinátatengelyek felcserélése, tükrözése, és a léptékváltás (nagyítás, kicsinyítés, összenyomás, széthúzás), elforgatjuk az ekliptika síkját a szimulált Naprendszerben.

Pont transzformáció esetén a tárgypontokhoz hozzárendeljük azok egy adott szempont szerinti hasonmását. Például: 3D-s tárgyak leképezése 2D-s képre, objektumok eltolása, forgatása, mozgatása, égitestek mozgatása tömegvonzás alapján. Affin transzformációk (egybevágósági és hasonlósági transzformációk) alkalmazása esetén pont képe pont, szakasz képe szakasz, felület képe felület, valamint metsző térelemek eredeti metszésvonala megegyezik azok leképezett metszésvonalával.

A számítógépes grafika területén az affin transzformációk általános alakja (mátrixosan):

A pont a B=(bx, by, bz) vektorral eltolható. A pont – a T=(t11, t12, …, t33) mátrixot használva – adott szöggel elforgatható, skálázható, tükrözhető. A számítógépes grafikában ezt a transzformációs mátrixot a homogén koordinátákkal alkalmazva, az összes geometriai transzformáció hatékonyan megvalósítható, visszavezethető mátrixok szorzására. Mindezt saját magunk is implementálhatjuk, de része a DirectX és OpenGL rendering pipeline-jának is.

Más módon is lehetne: egyenes és ehhez tartozó szög párossal is dolgozhatnánk.

A tömegvonzás elve

A tömegvonzás bármely két égitest között meghatározott, függ a gravitációs állandótól és az égitestek tömegétől egyenes arányban, az égitestek (tömeg)középpontjainak távolságától fordított arányban. Ez a Newton szerinti értelmezés, amelynek képlete:

A hatás-ellenhatás törvénye miatt a vonzás – egymás felé való gyorsulás – kölcsönös, a gyorsulás az égitestek tömegével fordítottan arányos, sosem nulla. A Naprendszerben a bolygók a Nap körül keringenek, és a bolygóknak lehetnek holdjaik. Egységesen kezelve: égitestek.

A tömegvonzásnak más elméleti megközelítései is vannak: Einstein gödör-modellje, Kepler törvényei, illetve differenciál-egyenletrendszer, integrálszámítás is használható a közelítő képlet helyett (csak ideális modell esetén pontszerű az égitest és gömbszimmetrikus azok tömegeloszlása), illetve ismeretes többféle értelmezés a rendszer/modell stabilitására: Lagrange pontok, Lyapunov stabilitás.

Az MVC modell

A klasszikus megközelítés szerint a szoftveres alkalmazások három, egymástól jól elkülöníthető szereppel rendelkező egységből állnak: modell (model), nézet (view), vezérlő (controller). A Java nyelv Swing komponensei az MVC architektúra szerint működnek.

A vezérlő reagál az érkező eseményre, hozzáfér a modell adatszerkezeteihez, azaz igénybe veszi a modell szolgáltatásait, valamint frissítheti a nézetet. A nézet a vezérlő frissítési kérésére a közvetlenül megkapott adatok alapján, vagy a modelltől elkért adatok alapján frissíti saját magát. A vezérlő határozza meg az alkalmazás, komponens, program működését. Egy modellt több nézet is használhat. A modell közvetlenül is üzenheti a nézetnek, hogy megváltozott. A nézet adja a látványt, amelyet angolul skin vagy „look and feel”-nek neveznek.

Programozás Java nyelven könyv – új, 2022-es kiadás

Megjelent a Programozás Java nyelven című könyv 2022-es kiadása.

Hosszú evolúciója van ennek a könyvnek. 2009-ben jelent meg az alapozó Programozási alapok és 2010-ben a haladó Programozási technológia című könyv. Ezek továbbfejlesztett, kibővített, egyesített változataként 2016-ban jelent meg a Programozás Java nyelven című könyv v1.0 változata. Elérkezett az ideje az újabb bővítésnek, kiegészítésnek, ez lett a v1.1 változat. A fejlesztő munka 2022. január-februárban valósult meg. A könyvnek továbbra is az egyik hívómondata: „500 oldal, 500 példa”. A példatár is jelentős frissítésen esett át.

A Java SE szoftverfejlesztő tanfolyamunk hallgatói megkapják a könyvet. Tananyagunk egyik alapja. A könyvet több iskolában, felsőoktatásban, szakképzésben, többféle OKJ tanfolyamon és újhullámos céges tanfolyamokon is használták/használják Magyarországon és a szomszédos országokban is.

A tankönyvből elsajátíthatók a strukturált és az objektumorientált programozás­hoz kapcsolódó alapismeretek. Az alkalmazott programozási nyelv a Java. Fejlesztői környezetként ingyenesen elérhető eszközöket használ: JDK/JRE, NetBeans.

A tankönyv 19 fejezetet tartalmaz.

Előszó
1. Bevezetés a programozásba
2. Út az integrált fejlesztőeszközig
3. Alapfogalmak
4. Kifejezések, értékadás
5. Szelekciók
6. Iterációk
7. Metódusok írása
8. Tömbök
9. Objektumorientált programozás
10. Java osztályok használata
11. Rendezés, keresés
12. Kivételkezelés
13. Kollekciók
14. Interfészek, belső osztályok
15. Öröklődés
16. Grafikus felhasználói felület felépítése
17. Eseményvezérelt programozás
18. Swing-komponensek
19. Fájlkezelés
Irodalomjegyzék

A fejezetek egymásra épülnek, hivatkoznak egymásra. Alapelv, hogy mindig csak éppen annyi elméleti ismeretet kell adni, ami egy-egy feladattípus, témakör megértéséhez elegendő és azonnal meg kell mutatni, hogyan kell az elméleti ismereteket alkalmazni a gyakorlatban. Így összekapcsolódnak az elmé­leti és gyakorlati ismeretek, ezután lehet rájuk építkezni.

A fejezetek felépítése egységes. Rövid, tömör elméleti ismereteket kö­vetően példának szánt feladatok következnek. A feladatok megfogalmazása vál­tozatos, mindig alkalmazkodik a már közben megszerzett, elvárható szint igé­nyeihez. A feladatok megoldása forráskódként, később osztálydiagramok formá­jában is szerepel. Ha szükséges, a program futtatása során előállított üzenetek, szövegek, képernyőképek is megjelennek. A megoldás elemzésekor részletes magyarázatok szerepelnek, amelyek során a kezdeti vissza-visszatérő utasításszintű magyarázatot fokozatosan felváltja a megoldás elvi alapjainak ismertetése.

A fejezetek végén gyakorló feladatok találhatók. Az elemzett és gyakorló felada­tok kölcsönösen egymásra épülnek, hivatkoznak egymásra. A biztos tudás érdekében minden gyakorló feladatot meg kell oldani!

A programozási tételek nagy hangsúlyt kaptak a tankönyvben. Az elemi prog­ramozási tételekhez kevés előismeret is elegendő, az összetett programozási téte­lekhez már több és biztos ismeret szükséges. Így a programozási tételek több fejezetben szétszórva találhatók meg.

Előfordul, hogy egy-egy feladat többször is előkerül, ilyenkor mindig alapvetően más elvű megoldás található hozzájuk. Ezeket érdemes összehasonlítani (sorszámok alapján könnyen megtalálhatók), hogy egyértelmű legyen, hogy milyen különb­ségek adódnak a különböző módszerek, megvalósított algoritmusok, adatszerke­zet miatt. Az összetettebb feladatokhoz készültek Demo programok is, amelyek lépésenként vezetnek a megértés felé.

A szerző ezúton is köszönetet mond minden kollé­gájának, minden hallgatójának, akik ötleteikkel, tanácsaikkal, javaslataikkal segítették munkáját, támogatták abban, hogy e tankönyv minél színvonalasabb legyen.

Ábécé sorrendben: Balogh Péter, Barta Milán, Berecz Antónia, Bódy Bence, Friedel Attila, Hollós Gábor, Kállai Miklós, Kiss Balázs, Lengyel Borisz István, Nagy Gábor, Nádai Gábor, Peck Tibor János, Ravasz Ildikó, Seres Iván, Szabó Ervin, Szakácsné Takács Brigitta, Szegedi Kristóf, Székely László, Vincze Bianka.

A Programozás Java nyelven című tankönyv megrendelhető a szerző, Kaczur Sándor honlapján.

Táblázatos komponens testreszabása

táblázat logo

táblázat logoA Java programozási nyelv egyik ismert GUI csomagja a swing. Ennek népszerű grafikus komponense az adatok táblázatos megjelenítését biztosító JTable komponens. A táblázatos megjelenítéshez több beállítás is szükséges. A JTable egy MVC komponens, így külön kezelendők a modell, nézet és a vezérlő funkcióihoz kötődő beállítások. A modell tárolja az adatokat például DefaultTableModel típusú objektumban, amiben szétválaszthatók a fejlécben és a többi cellákban található adatok. A nézethez tartozik a betűméret, a cellák színezése, az adatok igazítása, megjelenítése, a gördítősáv. A viselkedést, a felhasználói reakciót a vezérlő határozza meg, például rendezés, görgetés, fókusz, kijelölés, oszlopok sorrendjének cseréje.

Feladat

Készítsünk olyan Java swing-es kliensprogramot, amely tetszőleges adatforrásból (XML vagy JSON a hálózatról, JDBC adatbázis kapcsolatból, ORM leképzésből származó objektumokból) képes az átvett adatok grafikus felületen való táblázatos megjelenítésére JTable komponenssel! Építsünk arra, hogy az adatokon kívül metaadatok is rendelkezésünkre állnak! A megoldás legyen univerzális!

Képernyőképek

OracleHR képernyőkép

Modell

A táblázatos GUI komponenst kezdetben inicializálni kell, illetve a benne tárolt adatok is törölhetők, ha újrahasznosításra kerül a sor:

Ki kell nyerni a tároláshoz és a megjelenítéshez kötődő adatokat (1. lépés). A metaadatokból a for() ciklus előállítja az oszlopTomb-öt, és az oszlopTipusTomb-be kerülnek az Oracle adattípusból Java objektumtípusként megfeleltetett adatok. Előbbi a fejléc feliratainak szövegeit tartalmazza, és az utóbbi befolyásolja az egyes cellákban az igazítást, illetve hatással van adott oszlop rendezésére is:

Ki kell nyerni a tároláshoz és a megjelenítéshez kötődő adatokat (2. lépés). A while() ciklus végigjárja az eredménytábla sorait és Object típusú tömböt állít elő az összetartozó rekord mezőiből. Ezek először generikus listába kerülnek, majd onnan kétdimenziós Object típusú tömbbe:

Mi indokolja a tömbökből álló generikus lista ( adatLista) alkalmazását?

A while() ciklus végrehajtása előtt nem tudjuk lekérdezni, hogy mennyi rekordot kaptunk vissza, így nem tudjuk rögtön az adatTomb-be tenni az adatokat. A Java nyelvben a tömbök mérete fix, és a deklaráció során meg kell adni. Az eredménytábla metaadatai között megtalálható a mezők száma, ami felhasználható a kétdimenziós tömb oszlopszámaként. A generikus lista dinamikus, annyi elemből fog állni, ahány lépésben végrehajtódik a while() ciklus. Ezután a listától lekérdezhető az elemszáma ( adatLista.size()), és ezzel megvan a kétdimenziós tömb sorainak száma, ami eddig hiányzott. Persze használhatnánk Vector-t is a tömbökből álló generikus lista helyett (mert a DefaultTableModel-nek van olyan túlterhelt konstruktora, ami átvenné paraméterként), de ezt inkább nem tesszük, hiszen a Vector már régóta obsolete kollekció.

Előállítjuk a vizuális komponens mögötti adatmodellt. Öröklődéssel kiegészítjük két hasznos függvénnyel, így cellák rajzolása/renderelése és rendezése megkaphatja a szükséges adattípust ( getColumnClass()), valamint letiltható a cellák szerkeszthetősége ( isCellEditable()). Utóbbiak inkább a vezérléshez kötődnek, de modellen keresztül itt és így kell beállítani:

Végül a vizuális komponens mögötti adatmodellt kell átadni:

Nézet

Adott betűtípus, betűstílus és betűméret használható a táblázat fejlécében, celláiban, illetve a betűmérettől függhet a sorok magassága:

Hasznos ha JScrollPane típusú gördítősáv tartozik a táblázathoz, így dinamikusan megjeleníthető/elrejthető a függőleges/vízszintes gördítősáv:

Vezérlés

Az adatokhoz valahogyan hozzá kell jutni. Most JDBC kapcsolatot használunk és az Oracle HR sémából kérdezünk le adatokat, de a forráskód-részlet univerzális. A folyamat a következő:

  • Betöltjük a driver osztályt.
  • Autentikációval c kapcsolatot nyitunk az adatbázis-szerver felé.
  • Végrehajtjuk a lekérdező SQL parancsot.
  • Feldolgozzuk az eredményül kapott ResultSet típusú rs objektumot.
  • Végül lezárjuk a c hálózati kapcsolatot.

Ha engedélyezzük, akkor a megjelenő táblázat fejlécében az egyes oszlopok felirataira kattintva elérhetjük, hogy az adott oszlop típusának megfelelően növekvő vagy csökkenő sorrendbe átrendeződjenek az adatok:

A kivételkezelést nem részleteztük a fenti forráskódoknál, de természetesen kötelezően adott.

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java SE szoftverfejlesztő tanfolyam 45-52. óra: Adatbázis-kezelés JDBC alapon, illetve Java adatbázis-kezelő tanfolyam 9-12. óra: Oracle HR séma elemzése, 33-36. óra: Grafikus kliensalkalmazás fejlesztése JDBC alapon, 2. rész alkalmaihoz kapcsolódik.