
A mellékelt példaprogram megnyitása előtt a SolarSystem.pas-ban lévő komponenst telepítenie kell a Delphi alá. Ehhez válassza a Component - Install Component menüpontot.
A komponens használata
A komponens alapmérete 400x400. A Nap középen helyezkedik el. A Zoom tulajdonság állításával a komponens tartalmát nagyíthatjuk vagy kicsinyíthetjük. A nagyítás méretének megadásakor a 0.5–5 tartományból választhatunk értéket.
A komponens által megjelenített Naprendszer részletben a vízszintes és függőleges görgető sávok segítségével mozoghatunk.
Ha az Active tulajdonság értékét igazra állítjuk, akkor a bolygók elkezdenek keringeni a Nap körül. A keringés ütemezését az Interval tulajdonság állításával módosíthatjuk.
Amikor rákattintunk egy bolygóra, létrejön az OnClick esemény, amelyben megkapjuk a kiválasztott bolygó adatait.
procedure TForm1.SolarSystem1Click(Sender: TObject; PlanetName: String; PlanetWidth, SunDistance, RPS: Double);
Az eseményben a következő adatokat kapjuk meg: PlanetName – a bolygó neve, PlanetWidth – átmérő (km), SunDistance – távolság a Naptól (km), RPS – keringési sebesség (km/s).
A FindPlanet metódus segítségével a megadott indexű bolygó kerül a középpontba.
procedure FindPlanet(Index: Byte);
A bolygók indexelése eggyel kezdődik. Az első bolygó a Nap.
Egy bolygó adatait a GetPlanetData függvénnyel kérdezhetjük le.
procedure GetPlanetData(Index: Byte; var Name: String; var Width, RPS, SunDistance: Double);
Az első helyen a bolygó indexét kell megadnunk, hasonlóan, mint a FindPlanet metódus esetében. A következő 4 megadott változóba kerülnek az egyes adatok: név, átmérő, keringési sebesség, valamint naptávolság.
A komponens elkészítése
A TPlanet osztály egyetlen bolygó megjelenítéséért felelős. Az osztályt a TGraphicControl-ból származtatjuk.
Minden bolygónak tudnia kell saját adatait, méretét, színét és annak az Origónak a koordinátáit, amely körül kering. Az osztály FTimer időzítője ütemezi a bolygó elmozdulását, a megadott szögben. Az időzítő ütemét az Interval, aktivitását az Active property-vel befolyásolhatjuk.
A valós Naprendszer méretei nagyon nagyok és a bolygók között hatalmas átmérő távolságok vannak. Ezeket a méreteket arányosan kell megjelenítenünk. A nagyítások és forgások következtében számos koordináta transzformációra szükségünk lesz. Hogy minél pontosabb értékekkel számolhassunk, a bolygó aktuális koordinátáit valós számként jegyezzük fel, az XCoord és YCoord property-kben. Amikor ezek a tulajdonságok módosulnak, automatikusan módosulnak a Left és Top property-k is.
A komponenst úgy terveztük, hogy nagyítható legyen. A nagyításból következik, hogy nem láthatjuk mindig a teljes rendszert, csak egy részletét. A részletet görgető sávok segítségével vihetjük arrébb. A LastDeltaX és LastDeltaY tulajdonságokba jegyezzük fel a görgető sávok előző pozícióit.
A bolygó elforgását a DoTimer metódus végzi el. A forgatás az időzítő minden ütemében, a keringési sebesség mértékétől függően történik.
x:=XCoord-FOrigo.X;
y:=YCoord-FOrigo.Y;
Degree:=(PI/180)*(FRPS/10);
NewX:=x*Cos(Degree)+y*Sin(Degree);
NewY:=-x*Sin(Degree)+y*Cos(Degree);
XCoord:=NewX+FOrigo.X;
YCoord:=NewY+FOrigo.Y;
A forgatáshoz a koordináta-geometriában használt Pont elforgatása X fokkal képletet használjuk fel. A forgatásba bele kell számolnunk az origó koordinátáit is. Ez képezi azt a pontot, amely körül forgatunk.
Az egyes bolygók megjelenítéséhez szükséges egy konténer objektum. Erre a feladatra a TCustomPanel osztályt választottuk, ebből örökítettük a TSolarSystem osztályt.
A Create metódusban létre kell hoznunk az egyes bolygókat megjelenítő objektumokat, melyeket a Planets tömbben tárolunk.
Planets: array[1..10] of TPlanet;
Az első elem a Nap, a további indexeken a bolygók találhatóak, valóságos sorrendjüknek megfelelően.
A nagyon nagy bolygó átmérő különbségek miatt ügyelnünk kell arra, hogy minden bolygó megjelenjen. Ezt úgy tudjuk megtenni, hogy az egyes bolygók méretét nem engedjük 4 pixel alá.
A nagyítás mértékét az FZoom változó tárolja. Ennek értékét minden transzformációnál és méretezésnél figyelembe kell vennünk.
A bolygók méretezését a SetPlanetSizes metódus végzi el.
A Naprendszerben való mozgáshoz TScrollBar objektumokat használunk fel. Pozitív és negatív tartományban is tudnunk kell mozogni, ezért a Min és a Max tulajdonságokat egyaránt be kell állítanunk. A mozgást a DoChange metódus vezérli, amely akkor kerül meghívásra, ha a ScrollBar-ok pozíciója változik.
procedure DoChange(Sender: TObject);
A p változó TPoint típusú. Ebben tároljuk el a mozgatás során keletkező új origó koordinátáit.
p.x:=Self.FOrigo.x-FHorzScrollBar.Position;
p.y:=Self.FOrigo.y-FVertScrollBar.Position;
Amikor módosítjuk az XCoord és YCoord property-k értékét, számolnunk kell a ScrollBar-ok előző pozícióival is, majd értékük módosítása után a LastDeltaX és LastDeltaY el kell tárolnunk az új pozíció értékeket.
XCoord:=XCoord+LastDeltaX-FHorzScrollBar.Position;
YCoord:=YCoord+LastDeltaY-FVertScrollBar.Position;
LastDeltaX:=FHorzScrollBar.Position;
LastDeltaY:=FVertScrollBar.Position;
Azt hogy a ScrollBar-ok milyen tartományban mozoghatnak, a DoResize metódus határozza meg, amely a panel OnResize eseménye.
procedure DoResize(Sender: TObject);
Meg kell határoznunk a legutolsó bolygó naptól mért távolságát pixelekben.
MaxPos:=Round(Sqrt(Sqrt(Planets[10].SunDistance/2))*FZoom)+Planets[10].Width;
A Naptól mért távolság pixelekbe történő átalakításánál negyedik gyököt vonunk. Így jelentősen csökkentjük a távolság értékét és az egyes bolygóknál mért távolságok arányai is megmaradnak. A MaxPos értéke határozza meg a ScrollBar-ok Max értékét.
Az origót a 0,0 koordinátára állítottuk be. Ez azt jelenti, hogy a ScrollBar-ok Min értékéből ki kell vonnunk a komponens szélességét, illetve magasságát ahhoz, hogy a Nap középen legyen.
Min:=(-1)*MaxPos-Self.Width;
A nagyítást és a kicsinyítést a SetZoom metódus végzi el.
procedure SetZoom(const Value: Double);
Először minden koordinátát el kell osztanunk az aktuális nagyítás mértékével, majd miután az FZoom-ban beállítottuk az új nagyítási értéket, meg kell hívnunk a DoRsize és SetPlanetSize metódusokat, amelyek beállítják az új koordinátákat és méreteket. Fontos hogy a transzformáció alatt a ScrollBar-okat állítsuk 0 pozícióba.