Obrázky a PHP – šikmý vrh
Třetí článek série o tvorbě obrázků v PHP jsem se rozhodl pojmout trochu netradičním způsobem, a to sestavením aplikace, která bude generovat dráhu šikmého vrhu. Konečně si tedy budete moci vyzkoušet všechny dosud získané znalosti na komplexním příkladě a poznat sílu PHP při práci s obrázkem.
Celá aplikace se bude skládat ze dvou souborů formular.php a vysledek.php, přičemž v prvním z nich my zadáme údaje potřebné k výpočtu (křivka bude generována na základě zadaného úhlu a rychlosti) a na druhém již uvidíme očekávaný výsledek společně se všemi zadanými i dopočítanými hodnotami (zdrojový kód ke stažení).
Stránka formular.php
V souboru formular.php uživatel zadá rychlost letícího tělesa, gravitační zrychlení v daném místě a úhel, pod kterým je těleso vrženo. Počet znaků u jednotlivých položek je použitím parametru „maxlength“ limitován, aby se předešlo problémům, kdy by nepozorný uživatel dovedl aplikaci ke zhroucení například zadáním pětimístného celého čísla v položce úhel.
<form action=“vysledek.php“ method=“post“>
<table width=“400″ cellpadding=“5″ cellspacing=“0″>
<tr>
<th colspan=“2″ width=“400″><h1>Aplikace šikmý vrh</h1></th>
</tr>
<tr>
<td width=“200″>Zadejte úhel [°]:</TD>
<td width=“200″><input type=“text“ name=“uhel“ maxlength=“2″ /></td>
</tr>
<tr>
<td width=“200″>Zadejte rychlost [m*s<sup>-1</sup>]:</td>
<td width=“200″><input type=“text“ name=“rychlost“ maxlength=“3″ /></td>
</tr>
<tr>
<td width=“200″>Zadejte grav.zrychlení [m*s<sup>-1</sup>]:</td>
<td width=“200″><input type=“text“ name=“zrychleni“ maxlength=“4″ value=“9.81″ /></td>
</tr>
<tr>
<td colspan=“2″><input type=“submit“ value=“Odeslat“ /></td>
</tr>
</table>
</form>
Stránka formular.php
Druhý soubor, který tvoří jádro celé aplikace a zpracovává data z předchozího formuláře, je již podstatně delší a náročnější, rozebereme si ho proto podrobněji a po částech. Ta první je asi nejjednodušší a v ní se provede kontrola správnosti zadaných údajů na předchozím formuláři a následně výpis nám známých údajů včetně dopočítaného dostřelu:
<? /* Kontrola správnosti zadaných údajů */
if (!$rychlost)
die („<div>Nevyplnili jste položku ‚rychlost'</div>“);
if ((ereg („[[:digit:]]“, $rychlost))!=1)
die („<div>Formát zadané rychlosti není správný.</div>“);
if (!$uhel)
die („<div>Nevyplnili jste položku ‚úhel'</div>“);
if ((ereg („[[:digit:]]“, $rychlost))!=1)
die („<div>Formát zadaného úhlu není správný.</div>“);
if (!$zrychleni)
die („<div>Nevyplnili jste položku ‚zrychlení'</div>“);
if ((ereg („[[:digit:]]“, $zrychleni))!=1)
die („<div>Formát zadaného zrychlení není správný.</div>“);
?>
<table width=“640″ cellpadding=“5″ cellspacing=“0″>
<tr>
<th colspan=“4″ width=“640″><h1>Aplikace šikmý vrh – Výsledky</h1></th>
</tr>
<tr>
<th width=“160″>Úhel</th>
<th width=“160″>Rychlost</th>
<th width=“160″>Grav.zrychlení</th>
<th width=“160″>Dostřel</th>
</tr>
<tr>
<td width=“160″ align=“center“><? echo($uhel); ?> °</td>
<td width=“160″ align=“center“><? echo($rychlost); ?> m*s<sup>-1</sup></td>
<td width=“160″ align=“center“><? echo($zrychleni); ?> m*s<sup>-2</sup></td>
<td width=“160″ align=“center“><?
$uhel = deg2rad ($uhel);
$dostrel = $rychlost*$rychlost*sin(2*$uhel)/$zrychleni;
$dostrel = sprintf („%.2f“, $dostrel);
echo („$dostrel m“);
?></td>
</tr>
<tr>
<td colspan=“4″><hr /></td>
</tr>
V dalších částech souboru nás již čeká pouze zpracování a vygenerování obrázku. Nejprve však vytvoříme prázdný rastr o rozměrech 600×400 pixelů a alokujeme barvu pozadí, křivek a os. Určíme též cestu k souboru s fontem, který chceme do obrázku pro vykreslení textu použít, a nadefinujeme také $iterace
, která určí, po jaké době se bude iterovat při vykreslování křivky, přičemž platí, že čím vyšší číslo, tím větší hustota spojovacích puntíků. Vykreslování křivky totiž stojí na principu opakovaného průběhu v cyklu, kdy vždy spočítáme souřadnice x, y podle platných fyzikálních vzorců x = v0*t*cos(Uhel)
a y = v0*t*sin(Uhel)-1/2*g*t2
a v onom místě vykreslíme vyplněnou malou kružnici.
Ještě před samotným vykreslováním musíme spočítat konstantu, kterou vynásobíme dopočítané souřadnice x a y, abychom křivku buď roztáhli nebo zmenšili tak, aby se vešla do rastru a celý ho zaplnila. Konstantu spočítáme pro každou souřadnici zvlášť, porovnáme je a použijeme tu menší. Pro osu x je konstanta spočítána prostým vydělením šířky rastru dostřelem tělesa (záměrně je hodnota šířka udávána jako 560 místo 600, aby byl dodržen okraj). U osy y to tak jednoduché není – musíme spočítat maximální výšku, kterou by těleso dosáhlo při vrhu. Takže spustíme cyklus a porovnáváme aktuální výšku $aktual_y
s $nejvyssi_y
. Pokud je aktuální výška větší, pak $nejvyssi_y
přebírá její hodnotu a cyklus pokračuje. Pokud ne, dosáhli jsme maxima a těleso již začíná padat, proto cyklus stopneme. Zároveň s tím však získáme i čas, po který těleso stoupalo. Protože je stejný jako čas, po který by klesalo, stačí ho vynásobit dvěma a máme i celkovou dobu letu $doba_letu
, kterou tu v závěru této části necháme vypsat do pravého horního rohu.
<?
/* Vytvoření obrázku a definice některých konstant */
$obrazek = ImageCreate (600, 400); // Vytvoření obrázku
$pozadi = ImageColorAllocate ($obrazek, 242, 242, 173); // Alokace barvy pozadí
$krivka = ImageColorAllocate ($obrazek, 0, 0, 255); // Alokace barvy křivky
$osy = ImageColorAllocate ($obrazek, 204, 0, 51); // Alokace barvy osy x,y
$cesta = „c:\\windows\\fonts\\tahoma.ttf“; // Cesta k souboru s fontem
$iterace = $rychlost/2000; // Spočítání hodnoty pro iteraci
/* Cyklus pro zjištění nejvyššího položeného místa trajektorie a délky letu */
while (true) {
$time += $iterace;
$aktual_y = $rychlost*$time*sin($uhel)-1/2*$zrychleni*$time*$time;
if ($aktual_y>$nejvyssi_y)
$nejvyssi_y=$aktual_y;
else {
$doba_letu = $time*2;
break;
}
}
/* Výpočty konstant pro umístění křivky do obrázku */
$konstanta_x = 560/$dostrel;
$konstanta_y = 360/$nejvyssi_y;
if ($konstanta_x>$konstanta_y)
$konstanta=$konstanta_y;
else
$konstanta=$konstanta_x;
/* Cyklus vykreslující trajektorii křivky */
while (true) {
$cas += $iterace;
$x = $rychlost*$cas*cos($uhel)*$konstanta+20;
$y = ($rychlost*$cas*sin($uhel)-1/2*$zrychleni*$cas*$cas)*$konstanta+20;
$prepocet_y = 400-$y;
if ($y>20)
ImageFilledArc ($obrazek, $x, $prepocet_y, 5, 5, 0, 360, $krivka, „IMG_ARC_PIE“);
else
break;
}
ImageTTFText ($obrazek, 8, 360, 450, 15, $krivka, $cesta, „Doba letu: $doba_letu s“);
V poslední části nás čeká vykreslení os x, y a umístění zarážek na ně v místě maximální výšky a dostřelu, přičemž pod tyto zářezy ještě zapíšeme dosažené metry. Do pole $body
i $body_2
vložíme souřadnice tří bodů – trojúhelníku – který vyplníme barvou osy a tento trojúhelník bude v konečné podobě tvořit šipku na konci osy. K šipce ještě napíšeme jméno osy (x, y) a dílo je dokonáno. Vše zbývá pouze uložit a nechat následně zobrazit.
/* Vykreslení osy x se šipkami */
$konec_osy_x = $dostrel*$konstanta+35;
$konec_osy_y = 400-($nejvyssi_y*$konstanta+35);
$maxim_osa = 400-($nejvyssi_y*$konstanta+20);
$body[0] = 20;
$body[1] = $konec_osy_y;
$body[2] = 16;
$body[3] = $konec_osy_y+8;
$body[4] = 24;
$body[5] = $konec_osy_y+8;
ImageFilledPolygon ($obrazek, $body, 3, $osy); // Vykreslení šipky ve směru x
ImageLine ($obrazek, 20, 380, $konec_osy_x, 380, $osy); // Vykreslení osy ve směru x
ImageTTFText ($obrazek, 12, 360, $konec_osy_x-10, 375, $osy, $cesta, „x“); // Popis osy
ImageLine ($obrazek, $konec_osy_x-15, 375, $konec_osy_x-15, 386, $krivka); // Zářez pro dostřel
$dostrel=(int) $dostrel; // Převod dostřelu na integer a jeho vypsání pod zářez
ImageTTFText ($obrazek, 10, 360, $konec_osy_x-32, 398, $krivka, $cesta, „$dostrel m“);
/* Vykreslení osy y se šipkami */
$body_2[0] = $konec_osy_x;
$body_2[1] = 380;
$body_2[2] = $konec_osy_x-8;
$body_2[3] = 376;
$body_2[4] = $konec_osy_x-8;
$body_2[5] = 384;
ImageFilledPolygon ($obrazek, $body_2, 3, $osy); // Vykreslení šipky ve směru y
ImageLine ($obrazek, 20, 380, 20, $konec_osy_y, $osy); // Vykreslení osy ve směru y
ImageTTFText ($obrazek, 12, 360, 25, $konec_osy_y+10, $osy, $cesta, „y“); // Popis osy
ImageLine ($obrazek, 15, $konec_osy_y+15, 25, $konec_osy_y+15, $krivka); // Zářez pro max.výšku
$nejvyssi_y = (int) $nejvyssi_y; // Převod maximální výšky na integer a jeho vypsání pod zářez
ImageTTFText ($obrazek, 8, 90, 10, $maxim_osa+20, $krivka, $cesta, „$nejvyssi_y m“);
ImagePNG ($obrazek, „vrh.png“); // Uložení obrázku do souboru
ImageDestroy ($obrazek);
?>
<tr>
<td colspan=“4″ align=“center“>
<img src=“vrh.png“ width=“600″ height=“400″ alt=“Trajektorie šikmého vrhu“>
</td>
</tr>
</table>
Příklad samotný můžete ještě o mnohé obohatit po estetické stránce, já sám to zde nedělal, neboť si myslím, že ještě více použitých funkcí by jen zbytečně rozptylovalo a bránilo v pochopení. Ostatně tato křivka je pouze křivkou, kterou by těleso dosáhlo ve vakuu – ve vzduchu či jiném plynu by trajektorie vypadala trošku jinak.
Starší komentáře ke článku
Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.
Mohlo by vás také zajímat
-
Globální výpadek IT systémů: Může za to jediná aktualizace
19. července 2024 -
Proč je důležité tvořit obsah na váš web?
29. srpna 2024 -
Zabezpečení e-mailů: Jak můžete chránit vaši firemní komunikaci
13. prosince 2023
Nejnovější
-
Výkonný a kompaktní: ASOME Max Studio s výjimečným poměrem cena/výkon
11. listopadu 2024 -
Šokující data od Microsoftu: Kyberútoky rostou o stovky procent!
8. listopadu 2024 -
Chcete jedinečnou doménu? Objevte koncovky FOOD, MEME a MUSIC!
7. listopadu 2024 -
OpenAI představilo novou funkci ChatGPT Search
6. listopadu 2024