A nemzetközi Pi nap alkalmából (március 14) Java programmal grafikusan ábrázoljuk a π számjegyeit. Kiindulunk egy négyzet alakú grafikus felület középpontjából. Ezt tekintjük origónak. Sorra vesszük a π első néhány számjegyét: 100, 1000, 10000 paraméterezhető módon. Minden számjegyet egy rövid szakasszal ábrázolunk. A szakaszok egymást követik. Az előző végpontja megegyezik a következő kezdőpontjával. A rajzolás elejét és végét kör jelzi.
Tervezés
Az alábbi szabály alapján döntjük el, hogy a π előforduló számjegyei esetén melyik irányba és milyen színnel rajzolunk szakaszt:
A π első 100000 db számjegyét tároljuk egy szövegfájlban. Ömlesztve, sortörés, tizedesvessző nélkül. Így a π első 30 számjegye:
314159265358979323846264338327. A szövegfájl helyét a
String PI_FILE konstans jegyzi meg. A paraméternek megfelelően ebből vesszük az első
N db számjegyet. Ezt a Java program beolvassa egy
String típusú
pi szövegobjektumba. A számjegyek összetartozó adatait egy
Digit osztály rendeli egymáshoz. Ennek három adattagja van: melyik számjegy:
int digit, melyik irányba kell szakaszt rajzolni
java.awt.Point direction, milyen színnel kell szakaszt rajzolni
java.awt.Color color. A tízféle színt egy konstans tömb tárolja:
Color[] COLORS.
Részletek a Java forráskódból
A π tízféle számjegyéből az alábbi forráskód-részlettel létrejön egy tömb adatszerkezet:
Digit[] digits. A koordináták/vektorok kiszámítása követi az analóg óra számlapjának 36 fokonként való felosztását.
|
for(int i=0; i<10; i++) { Point p=new Point( (int)(Math.cos(Math.toRadians(i*36-90))*LINE_LENGTH), (int)(-Math.sin(Math.toRadians(i*36-90))*LINE_LENGTH) ); digits[i]=new Digit(i, p, COLORS[i]); } |
A rajzoláshoz szükséges még néhány konstans: milyen vastag vonalat kell rajzolni:
double PEN_RADIUS, mekkora átmérőjű kör jelzi a rajzolás kezdő- és végpontját:
double POINT_RADIUS, milyen hosszú vonalat kell rajzolni:
int LINE_LENGTH, a rajzterületet mekkorára kell méretezni/skálázni:
int SCALE.
Mindezek alapján az alábbi forráskód-részlet vizualizálja a π számjegyeit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
private void piDraw() { StdDraw.setScale(-SCALE, SCALE); StdDraw.setPenRadius(PEN_RADIUS); Point p1=new Point(0, 0); StdDraw.setPenColor(digits[3-1].getColor()); StdDraw.circle(p1.x, p1.y, POINT_RADIUS); for(int i=0; i<PI.length(); i++) { int digit=Integer.parseInt(""+PI.charAt(i)); Point p2=new Point( p1.x+digits[digit].getDirection().x, p1.y+digits[digit].getDirection().y); StdDraw.setPenColor(digits[digit].getColor()); StdDraw.line(p1.x, p1.y, p2.x, p2.y); p1=p2; } StdDraw.circle(p1.x, p1.y, POINT_RADIUS); } |
Eredmény
Eredményül ezek az ábrák készíthetők el:
A rajzoláshoz felhasználtuk az
StdDraw osztályt, amely ennek a tankönyvnek a példatárából származik: Robert Sedgewick, Kevin Wayne: Computer Science: An Interdisciplinary Approach, 1st edition, Princeton University, Addison-Wesley Professional, 2016, ISBN 978-0134076423. Az osztály metódusaival könnyen beállítható a nézőpont, a vízszintes/függőleges skála, a rajzoláshoz használt toll mérete/színe és a grafikai primitívek közül csak a kör és szakasz ábrázolása szükséges.
Korábban is megemlékeztünk néhány közelítő algoritmus – Viète-féle sor, Leibniz-féle sor, Wallis-formula, Csebisev-sor – implementálásával erről az ünnepnapról: Nemzetközi Pi nap. Ajánljuk korábbi blog bejegyzéseinket rajzolás, animáció, grafika címkékkel, illetve ASCII művészet Java-ban.
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 szakmai moduljának 5-8. óra: Vezérlési szerkezetek, 13-16. óra: Tömbök, 17-28. óra: Objektumorientált programozás, 29-36. óra: Grafikus felhasználói felület, 37-44. óra: Fájlkezelés alkalmaihoz kötődik.