Toto je čtvrtá varianta hry Inspiro, která kreslí Bézierovy hodiny.
Na této stránce ukazuje nahodilý čas, který můžete změnit klávesou F5 - reload.
Na tomto odkazu jsou hodiny, které se automaticky aktualizují, ale prosím nenechávejte je na běžet příliš dlouho (>5 minut), ať se zbytečně nepřetěžuje server. (Zastavit je můžete pomocí klávesy ESC a znova spustit pomocí klávesy F5)
Bohužel ještě nemám dodělaný výstup a nastavování parametrů, každopádně použitelné parametry jsou některé z následujících :
cifernik.php?nahodile=1&hodina=13&minuta=23&sekunda=33&pozadir=255&pozadig=255&pozadib=255&popredir=0&popredig=0&popredib=0&rafier=200&rafieg=0&rafieb=0&picWidth=400&picHeight=400&pomer=0.8&pomers=0.2&krok=100&vzdalenost=3&body=1
Nahodilost 0/1
Časové paramtery jsou jasné
koncová písmena RGB jsou barvy 0-255
picWidth, picHeight - Velikost obrázku v pixelech
pomer je poměr mezi velkou a malou rafičkou
pomers je míra zakřivení beriezovy křivky sekundovou rafií, normálně je 0.2, při hodnotách okolo 2 už je to hodně odvážná křivka
krok a vzdálenost udávají plynulost křivky. Krok optimálně 100, pokud se stane že skok je větší než 3 pixely, tak to dopočítá i mezi body (pojistka vzdálenosti mezi dvěma body)
body 0/1 - zobrazí čtyři body, které definují, Bezierovu křivku (občas jsou mimo hranice obrázku)
<?php
if ($vypis!=1) Header("Content-type: image/png");
//defaultni hodnoty proměnných
if (! isset($cara)) $cara=3;//sila cary
if (! isset($pozadir)) $pozadir=255;//128 0 cerna 255 bila
if (! isset($pozadig)) $pozadig=255;//0
if (! isset($pozadib)) $pozadib=255;//0
if (! isset($popredir)) $popredir=0;//150 barva ciferniku
if (! isset($popredig)) $popredig=0;//60
if (! isset($popredib)) $popredib=0;//0
if (! isset($poprediSr)) $poprediSr=200;//barva sekundoveho bodu
if (! isset($poprediSg)) $poprediSg=200;//60
if (! isset($poprediSb)) $poprediSb=0;//0
if (! isset($rafier)) $rafier=200;
if (! isset($rafieg)) $rafieg=0;
if (! isset($rafieb)) $rafieb=0;
if (! isset($bodyr)) $bodyr=0;
if (! isset($bodyg)) $bodyg=100;
if (! isset($bodyb)) $bodyb=0;
if (! isset($picWidth)) $picWidth=800;
if (! isset($picHeight)) $picHeight=800;
if (! isset($pomer)) $pomer=0.6; //mezi velkou a malou ručičkou
if (! isset($pomers)) $pomers=0.2; //poměr sekundove rafiky a prohnutí krivky
if (! isset($krok)) $krok=100; //čím je krok menší, tím je křivka zubatější, ale vypočet rychlejší
if (! isset($vzdalenost)) $vzdalenost=3; //zpresni vypocet, pokud ke vzdalenost mezi dvema body v pixelech mensi nez tato promenna
// plynulost křivky je tedy kompromis mezi krokem a vzdalenosti, vypočet ale bude rychlejší, když je víc kroků a menší vzdálenost. Když je málo kroků, tak to víc iteruje. Vzdálenost je jen pojistka pro nečekané skoky.
$stredx = $picWidth / 2;
$stredy = $picHeight / 2;
$prumer=min($stredx,$stredy)-10; //průměr ciferníku
$image=ImageCreate($picWidth+1,$picHeight+1);
$cPozadi=ImageColorAllocate($image,$pozadir,$pozadig,$pozadib); //pozadi
$cPopredi=ImageColorAllocate($image,$popredir,$popredig,$popredib); //popredi
$cPoprediS=ImageColorAllocate($image,$poprediSr,$poprediSg,$poprediSb); //popredi sekundoveho bodu
$cRafie=ImageColorAllocate($image,$rafier,$rafieg,$rafieb); //popredi
$cBody=ImageColorAllocate($image,$bodyr,$bodyg,$bodyb); //body
imagesetthickness($image, $cara);
$cas=localtime(time(),true);
if ($vypis==1) print_r($cas);
if (isset($sekunda)==false) {
if ($nahodile==1) $sekunda=rand(0,59);
else $sekunda=$cas["tm_sec"];
}
$alfas=2*pi()*$sekunda/60; //úhel sekundové rafie, samozřejmě v radianech
$vsekundax=$stredx+($prumer+6)*sin($alfas); // počítá koordináty ručiček hodin
$vsekunday=$stredy-($prumer+6)*cos($alfas);
$sekundax=$stredx+$pomers*$prumer*sin($alfas); // počítá koordináty ručiček hodin
$sekunday=$stredy-$pomers*$prumer*cos($alfas);
if (isset($minuta)==false) {
if ($nahodile==1) $minuta=rand(0,59);
else $minuta=$cas["tm_min"];
}
$alfam=2*pi()*$minuta/60;
$minutax=$stredx+$prumer*sin($alfam);
$minutay=$stredy-$prumer*cos($alfam);
$iminutax=$stredx-$prumer*sin($alfam); //inverzni vektory pro vychozi body bezierovy krivky
$iminutay=$stredy+$prumer*cos($alfam);
if (isset($hodina)==false) {
if ($nahodile==1) $hodina=rand(0,11);
else $hodina=$cas["tm_hour"];
}
$alfah=2*pi()*$hodina/12 + 2*pi()*$minuta/60/12; //zohledňuje minutový pohyb hodinové rafie
$hodinax=$stredx+$pomer*$prumer*sin($alfah );
$hodinay=$stredy-$pomer*$prumer*cos($alfah);
$ihodinax=$stredx-$pomer*$prumer*sin($alfah);
$ihodinay=$stredy+$pomer*$prumer*cos($alfah);
//spočítá výchozí body bezierovy křivky - volné pole pro experimentování - $p2 a $p3 je možno definovat libovolně
$p1=array($minutax, $minutay); //vychozí bod
$p2=array($iminutax+($sekundax-$stredx), $iminutay+($sekunday-$stredy)); //kam ukazuje prvni vektor
$p3=array($ihodinax-($sekundax-$stredx), $ihodinay-($sekunday-$stredy)); //kam ukazuje druhy vektor
$p4=array($hodinax, $hodinay); //koncový bod
// Calculate the coordinate of the Bezier curve at $t = 0..1
function Bezier_eval($p1,$p2,$p3,$p4,$t) {
//čtyři body (vektory - $p) zredukuje na tři vážením přes $t, což je něco jako procento od 0 do 100% čili od začátku do konce křivky.
//Například pro $t=1% vezme 99% z bodu $p1 a jen 1% z bodu $p2.
//Vzniknou tři vektory $q. Z nich pak uděla stejným stylem dva vektory $r a nakonec jeden, který vrátí (return).
//Tak se ke každému procentu $t výsledné křivky přiřadí jeden bod křivky.
//Stejně by se postupovalo při jakémkoli jiném počtu výchozích vektorů.
//Každopádně toto je podstata Bezierovy křivky, kterou jsem díky tomuto pochopil ve svých 49 letech. Ach, co jsem dělal doposud, že jsem toto ještě nevěděl! :-)
// lines between successive pairs of points (degree 1)
$q1 = array((1-$t) * $p1[0] + $t * $p2[0],(1-$t) * $p1[1] + $t * $p2[1]);
$q2 = array((1-$t) * $p2[0] + $t * $p3[0],(1-$t) * $p2[1] + $t * $p3[1]);
$q3 = array((1-$t) * $p3[0] + $t * $p4[0],(1-$t) * $p3[1] + $t * $p4[1]);
// curves between successive pairs of lines. (degree 2)
$r1 = array((1-$t) * $q1[0] + $t * $q2[0],(1-$t) * $q1[1] + $t * $q2[1]);
$r2 = array((1-$t) * $q2[0] + $t * $q3[0],(1-$t) * $q2[1] + $t * $q3[1]);
// final curve between the two 2-degree curves. (degree 3)
return array((1-$t) * $r1[0] + $t * $r2[0],(1-$t) * $r1[1] + $t * $r2[1]);
}
// Calculate the squared distance between two points - pythagorova věta. Alespoň člověk ví, k čemu je dobrá.
function Point_distance2($p1,$p2) {
$dx = $p2[0] - $p1[0];
$dy = $p2[1] - $p1[1];
return $dx * $dx + $dy * $dy;
}
// Convert the curve to a polyline
function Bezier_convert($p1,$p2,$p3,$p4,$vzdalenost, $krok) {
$t1 = 0.0;
$prev = $p1; //od bodu $p1 az po bod $p4 spočítá po $krok- krocích body bezierovy křivky
$t2 = 1/$krok; //alespon dva kroky
$tol2 = $vzdalenost * $vzdalenost; //kvadrat k pythagorově větě, viz Point_distance2
$result []= $prev[0]; // [] automaticky přida další index či prvek ve vektoru result
$result []= $prev[1];
while ($t1 < 1.0) {
if ($vypis==1) print("t2 je $t2; t1 je $t1<br>");
if ($t2 > 1.0) { $t2 = 1.0; } //blbovzdorná pojistka
$next = Bezier_eval($p1,$p2,$p3,$p4,$t2);
$dist = Point_distance2($prev,$next);
// while (0==1) { // vypíná efekt vzdálenosti
while ($dist > $tol2) {
// Halve the distance until small enough; pojistka pro nenadále skoky křivky, radeji dat vic kroku, pak je rychlejší výpočet
$t2 = $t1 + ($t2 - $t1) * 0.5;
$next = Bezier_eval($p1,$p2,$p3,$p4,$t2);
$dist = Point_distance2($prev,$next);
}
// the image*polygon functions expect a flattened array of coordiantes
$result []= $next[0]; //přidává další a další body
$result []= $next[1];
$t1 = $t2;
$prev = $next;
$t2 = $t1 + 1/$krok;
}
$result []= $p4[0]; //nakonec vložit i koncový bod křivky
$result []= $p4[1];
return $result; //vraci dlouhy seznam bodů bezierovy křivky
}
$polygon = Bezier_convert($p1, $p2, $p3, $p4, $vzdalenost, $krok);
if ($vypis==1) print_r($polygon, true);
$pocetbodu=count($polygon)/2-1; // děleno dvěma protože jsou to souřadnice xy, tedy bodu je pravě polovina
for ($i=0;$i<$pocetbodu;$i++) {
imageline($image, $polygon[2*$i], $polygon[2*$i+1], $polygon[2*$i+2], $polygon[2*$i+3], $cRafie); //dva po sobě jdoucí body XY
}
// imagepolygon($image,$polygon,count($polygon)/2,$cRafie);
// imageline($image, $minutax, $minutay, $hodinax, $hodinay, $cPozadi); //toto odmaže přímku polynomu mezi koncovými body $p1 a $p4
// starsi verze - může se hodit, pokud bychom chtěli uzavřenou křivku
imagefilledellipse ($image , $stredx, $stredy, 1 , 1 , $cPopredi); //střed ciferníku
imagefilledellipse ($image , $vsekundax, $vsekunday, 10 , 10 , $cPoprediS ); //sekundová ručička - přesněji sekundovy bod - velikost a barva
if ($body==1){
imagefilledellipse ($image , $p1[0], $p1[1], 10 , 10 , $cBody); //zakladní body
imagefilledellipse ($image , $p2[0], $p2[1], 10 , 10 , $cBody); //zakladní body
imagefilledellipse ($image , $p3[0], $p3[1], 10 , 10 , $cBody); //zakladní body
imagefilledellipse ($image , $p4[0], $p4[1], 10 , 10 , $cBody); //zakladní body
}
for ($i=0; $i<60;$i++) //cifernik minuty (polarni souradnice)
{
imagefilledellipse ($image , $stredx+$prumer*sin(2*pi()*$i/60),
$stredy-$prumer*cos(2*pi()*$i/60), 2 , 2 , $cPopredi);
}
for ($i=0; $i<12;$i++) //cifernik hodiny
{
imagefilledellipse ($image , $stredx+$pomer*$prumer*sin(2*pi()*$i/12),
$stredy-$pomer*$prumer*cos(2*pi()*$i/12), 2 , 2 ,$cPopredi);
imagefilledellipse ($image , $stredx+$prumer*sin(2*pi()*$i/12),
$stredy-$prumer*cos(2*pi()*$i/12), 6 , 6 ,$cPopredi);
}
$cas=str_pad($hodina, 2, '0', 'STR_PAD_LEFT').":".str_pad($minuta, 2, '0', 'STR_PAD_LEFT').":".str_pad($sekunda, 2, '0', 'STR_PAD_LEFT');
if ($text==1) imagefttext ($image, 10, 0, 10, 20, $cRafie, "arial.ttf", "$cas");
Imagepng($image);
ImageDestroy($image); //Například baba jaga, když letí ve hmoždíři, tak za sebou zametá. Toto má stejnou funkci.
if ($vypis==1): //chaoticke ad hoc vypisy pro debugování
$f = fopen("background4.htm", "w");
fputs($f, "<html><body>");
$promenne=print_r($polygon, true);
fputs($f, "$promenne");
$promenne="picWidth=".$picWidth."&picHeight=".$picHeight."&pozadir=".$pozadir."&pozadig=".$pozadig."&pozadib=".$pozadib."&popredir=".$popredir."&popredig=".$popredig."&popredib=".$popredib."&pomer=".$pomer."&elipsa=".$elipsa."&r1=".$r1."&r2=".$r2."&r3=".$r3."&orientace=".$orientace."&krok=".$krok."&kroku=".$kroku;
fputs($f, $promenne);
// fputs($f, "<a href=inspiro3.php?".$promenne.">hodnoty vlozit do formulare inspiro3.php</a><br>");
// fputs($f, "<a href=background3.php?".$promenne.">ulozene hodnoty z background3.php</a><br>");
fputs($f, "</body></html>");
fclose($f);
endif;
?>