immagini.php
<?php
class gf_cartesiano {
// dimensioni immagine totale
var $_x_size_;
var $_y_size_;
// coordinate origine assi
var $_x0_;
var $_y0_;
// dimensioni asse x
var $_xi_;
var $_xf_;
var $_x_axis_;
// dimensioni asse y
var $_yi_;
var $_yf_;
var $_y_axis_;
// l'immagine
var $image;
// qualche colore
var $white;
var $black;
var $red;
var $blue;
var $yellow;
// uso un po' strano perche' non settata in modo valido dal costruttore
var $scale;
Function gf_cartesiano(&$x_axis, &$y_axis)
// costruttore
{
// settta le dimensioni dell'immagine
$this->_x_size_ = 480;
$this->_y_size_ = 480;
// coordinate origine assi
$this->_x0_ = 30;
$this->_y0_ = $this->_y_size_ - 30;
// dimensioni asse x
$this->_xi_ = 10;
$this->_xf_ = $this->_x_size_ - $this->_xi_;
$this->_x_axis_ = $this->_xf_ - $this->_x0_ - 10;
$x_axis = $this->_x_axis_;
// dimensioni asse y
$this->_yi_ = 10;
$this->_yf_ = $this->_y_size_ - $this->_yi_;
$this->_y_axis_ = $this->_yf_ - $this->_y0_ - 10;
$y_axis = $this->_y_axis_;
// crea lo sfondo
$this->image = imagecreate($this->_x_size_ , $this->_y_size_ );
// alloca i colori
$this->white = ImageColorAllocate($this->image, 255,255,255);
$this->black = ImageColorAllocate($this->image, 0,0,0);
$this->red = ImageColorAllocate($this->image, 255,0,0);
$this->green = ImageColorAllocate($this->image, 0,255,0);
$this->blue = ImageColorAllocate($this->image, 0,0,255);
$this->magenta = ImageColorAllocate($this->image, 255,0,255);
$this->yellow = ImageColorAllocate($this->image, 255,255,0);
$this->darkgreen = ImageColorAllocate($this->image, 0,100,0);
$this->darkorange = ImageColorAllocate($this->image, 255,127,0);
// assegna un valore a caso a scale
$this->scale=1;
// ritorna il puntatore all'immagine
return $this->image;
}
Function fq_col($col)
// colora il primo quadrante
{
$tile = imageCreateFromPNG('images/regione_amm.png');
if ($tile == false) { die ('Unable to open image'); }
imageSetTile ($this->image, $tile);
// imagefilledrectangle($this->image, 30, 20, 460, 450, $col);
imagefilledrectangle($this->image, 30, 20, 460, 450, IMG_COLOR_TILED);
}
Function assi($vertici, $scale)
// disegna gli assi e scrive i valori
{
// disegna asse x
imageline($this->image,$this->_xi_,$this->_y0_,$this->_xf_,$this->_y0_,$this->black);
// disegna frecce asse x
imageline($this->image,$this->_xf_-10,$this->_y0_-10,$this->_xf_,$this->_y0_,$this->black);
imageline($this->image,$this->_xf_-10,$this->_y0_+10,$this->_xf_,$this->_y0_,$this->black);
// scrivi O nell'origine
imagechar($this->image,3,$this->_x0_-25,$this->_y0_+10,"O",$this->black);
// disegna lettere asse x e stanghette
imagechar($this->image,3,$this->_xf_-10,$this->_y0_+10,"x",$this->black);
imagechar($this->image,2,$this->_xf_,$this->_y0_+15,"1",$this->black);
for ($i=0; $i<count($vertici); $i+=2)
if ($vertici[$i] > 0) {
$x = $this->map_x ($vertici[$i], $scale);
imageline($this->image, $x, $this->_y0_, $x, $this->_y0_+5, $this->black);
$lettere=number_format($vertici[$i],2,",",".");
imagestring($this->image, 3, $x - 10, $this->_y0_+10, $lettere, $this->black);
}
// disegna asse y
imageline($this->image,$this->_x0_,$this->_yi_,$this->_x0_,$this->_yf_,$this->black);
// disegna frecce asse y
imageline($this->image,$this->_x0_-10,$this->_yi_+10,$this->_x0_,$this->_yi_,$this->black);
imageline($this->image,$this->_x0_+10,$this->_yi_+10,$this->_x0_,$this->_yi_,$this->black);
// disegna lettere asse y
imagechar($this->image,3,$this->_x0_-25,$this->_yi_+5,"x",$this->black);
imagechar($this->image,2,$this->_x0_-15,$this->_yi_+10,"2",$this->black);
for ($i=1; $i<count($vertici); $i+=2)
if ($vertici[$i] > 0) {
$y = $this->map_y ($vertici[$i], $scale);
imageline($this->image, $this->_x0_-5, $y, $this->_x0_, $y, $this->black);
$lettere=number_format($vertici[$i],2,",",".");
imagestring($this->image, 3, $this->_x0_ - 30, $y, $lettere, $this->black);
}
}
Function map_x ($vx, $scale)
/* ritorna il valore della coordinata x sull'immagine corrispondente al punto
di coordinata vx nell'asse cartesiano, fissato il parametro di scala */
{
return $this->_x0_ + round($scale * $vx);
}
Function map_y ($vy, $scale)
/* ritorna il valore della coordinata y sull'immagine corrispondente al punto
di coordinata vy nell'asse cartesiano, fissato il parametro di scala */
{
return $this->_y0_ - round($scale * $vy);
}
Function ruota ($x, $y, &$xr, &$yr, $alpha)
// ruota (x, y)-(0 ,0) di un angolo alpha
{
$xr = $x * cos($alpha) - $y * sin ($alpha);
$yr = $y * cos($alpha) + $x * sin ($alpha);
}
Function line($scale, $vxi, $vyi, $vxf, $vyf, $col)
/* disegna il segmento corrispondente a quello PQ fra P=(vxi, vyi) e q=(vxf, vyf) */
{
// calcolo nuove coordinate
$xi = $this->map_x ($vxi, $scale);
$xf = $this->map_x ($vxf, $scale);
$yi = $this->map_y ($vyi, $scale);
$yf = $this->map_y ($vyf, $scale);
// disegna il segmento
imageline($this->image,$xi,$yi,$xf,$yf,$col);
}
Function freccia($scale, $vxi, $vyi, $vxf, $vyf, $col)
/* disegna la freccia P-Q fra P=(vxi, vyi) e q=(vxf, vyf) con ampiezza 45 gradi*/
{
/* R R __. P
45° \ /\ S
Q ----------> P / angolo di cui calcolo sin e cos
45° / _______ /)______________
S Q x
*/
// calcolo nuove coordinate
$xi = $this->map_x ($vxi, $scale);
$xf = $this->map_x ($vxf, $scale);
$yi = $this->map_y ($vyi, $scale);
$yf = $this->map_y ($vyf, $scale);
// trasliamo P-Q nell'origine per fare i conti
$x = $xf-$xi;
$y = -($yf-$yi);
$modulo = sqrt($x*$x+$y*$y);
// calcola seno e coseno dell'angolo fra il segmento e l'asse x
if (! $modulo)
return 0;
$sin_ = $y / $modulo;
$cos_ = $x / $modulo;
// calcola gli estremi dei segmenti delle frecce
// r rotazione di 45° del vettore di modulo 10 e direzione di Q-P
$this->ruota (-10 * $cos_, -10 * $sin_, $xr, $yr, M_PI/6);
$xr += $xf;
$yr = $yf - $yr;
// s rotazione di -45° del vettore di modulo 10 e direzione di Q-P
$this->ruota (-10 * $cos_, -10 * $sin_, $xs, $ys, 11*M_PI/6);
$xs += $xf;
$ys = $yf - $ys;
// disegna il segmento
imageline($this->image,$xi,$yi,$xf,$yf,$col);
imagefilledpolygon($this->image, array($xr, $yr, $xs, $ys, $xf, $yf), 3, $col);
//imageline($this->image,$xr,$yr,$xf,$yf,$col);
//imageline($this->image,$xs,$ys,$xf,$yf,$col);
}
Function cerchio ($scale, $vx0, $vy0, $l, $col)
/* disegna una circonferenza di raggio r pixel e centro P=(vx, vy) */
{
$x0 = $this->map_x ($vx0, $scale);
$y0 = $this->map_y ($vy0, $scale);
$l2=round($l/2);
//imagefilledellipse($this->image,$x0,$y0,$r,$r,$col); // non gestita da vecchie gd
imagefilledrectangle($this->image,$x0-$l2,$y0-$l2,$x0+$l2,$y0+$l2,$col);
}
Function ping($name)
// scrive l'immagine in formato PNG nel file di nome $name
{
imagepng($this->image, $name);
}
Function plotta_disequazione($ax, $ay, $b, $lge, $scale, $col)
/* disegna i segmenti corrispondenti alla dis/equazione immesssa e cancella
la parte che non verifica la disequazione usando il colore $col */
{ // ax x + ay y lge b
// costanti
$max = $this->_x_axis_ / $scale;
$p0x = 0; $p0y = 0;
$p1x = $max; $p1y = 0;
$p2x = $max; $p2y = $max;
$p3x = 0; $p3y = $max;
if ($ax == 0) { // ay y = b
$vx0 = 0;
$vx1 = $max;
$vy0 = $b / $ay;
$vy1 = $vy0;
// se si tratta di un'equazione, scrivi l'immagine e ritorna
if (! strcmp($lge, "=")) {
$this->line($scale, $vx0, $vy0, $vx1, $vy1, $col);
return 0;
}
// si tratta di una disequazione ay y <> b
if( strstr ($lge, ">"))
if ($ay>0)
$cancella_sotto=true;
else
$cancella_sotto=false;
else
if ($ay>0)
$cancella_sotto=false;
else
$cancella_sotto=true;
if ($cancella_sotto) {
if ($vy0 > 0)
imagefilledrectangle($this->image, $this->map_x(0, $scale), $this->map_y($vy0, $scale), $this->map_x($max, $scale), $this->map_y(0, $scale), $col);
} else
if ($vy0 > 0)
imagefilledrectangle($this->image, $this->map_x(0, $scale), $this->map_y($max, $scale), $this->map_x($max, $scale), $this->map_y($vy0, $scale), $col);
else
imagefilledrectangle($this->image, $this->map_x(0, $scale), $this->map_y($max, $scale), $this->map_x($max, $scale), $this->map_y(0, $scale), $col);
return 0;
}
if ($ay) {
$m = -$ax/$ay;
$q = $b/$ay;
} else { // ax x = b
$vx0 = $b / $ax;
$vx1 = $vx0;
$vy0 = 0;
$vy1 = $max;
// se si tratta di un'equazione, scrivi l'immagine e ritorna
if (! strcmp($lge, "=")) {
$this->line($scale, $vx0, $vy0, $vx1, $vy1, $col);
return 0;
}
// si tratta di una disequazione
if( strstr ($lge, ">"))
if ($ax>0)
$cancella_sx=true;
else
$cancella_sx=false;
else
if ($ax>0)
$cancella_sx=false;
else
$cancella_sx=true;
if ($cancella_sx) {
if ($vx0 > 0)
imagefilledrectangle($this->image, $this->map_x(0, $scale), $this->map_y($max, $scale), $this->map_x($vx0, $scale), $this->map_y(0, $scale), $col);
} else
if ($vx0 > 0)
imagefilledrectangle($this->image, $this->map_x($vx0, $scale), $this->map_y($max, $scale), $this->map_x($max, $scale), $this->map_y(0, $scale), $col);
else
imagefilledrectangle($this->image, $this->map_x(0, $scale), $this->map_y($max, $scale), $this->map_x($max, $scale), $this->map_y(0, $scale), $col);
return 0;
}
// setta i vertici della retta ax x + ay y = b
if ($m >= 0)
if ($q >= 0) {
$vx0 = 0; $vy0 = $q;
if (($vy1 = $m*$max+$q) < $max) {
$vx1 = $max;
} else {
$vy1 = $max;
$vx1 = ($max-$q)/$m;
}
} else {
$vx0 = $b/$ax; $vy0 = 0;
if (($vy1 = $m*$max+$q) < $max) {
$vx1 = $max;
} else {
$vy1 = $max;
$vx1 = ($max-$q)/$m;
}
}
else { // m<0
if ($q >= 0) {
$vx0 = 0; $vy0 = $q;
if (($vy1 = $m*$max+$q) > 0) {
$vx1 = $max;
} else {
$vy1 = 0;
$vx1 = $b/$ax;
}
}
}
// se si tratta di un'equazione, scrivi l'immagine e ritorna
if (! strcmp($lge, "=")) {
$this->line($scale, $vx0, $vy0, $vx1, $vy1, $col);
return 0;
}
// si tratta di una disequazione
if( strstr ($lge, ">"))
if ($ay>0)
$cancella_sotto=true;
else
$cancella_sotto=false;
else
if ($ay>0)
$cancella_sotto=false;
else
$cancella_sotto=true;
if ($m >= 0) // m >= 0
if ($q >= 0) { // m, q >= 0
if (! $cancella_sotto) { // m, q >= 0: colora il poligono piu' alto
if ($vx1 == $max)
$array = array($vx0, $vy0, $vx1, $vy1, $p2x, $p2y, $p3x, $p3y);
else
$array = array($vx0, $vy0, $vx1, $vy1, $p3x, $p3y);
} else { // m, q >= 0: colora il poligono in basso
if ($vx1 == $max)
$array = array($vx0, $vy0, $vx1, $vy1, $p1x, $p1y, $p0x, $p0y);
else
$array = array($vx0, $vy0, $vx1, $vy1, $p2x, $p2y, $p1x, $p1y, $p0x, $p0y);
}
} else { // m>=0, q<0
if (! $cancella_sotto) { // m>=0, q<0: alto
if ($vx1 == $max)
$array = array($vx0, $vy0, $vx1, $vy1, $p2x, $p2y, $p3x, $p3y, $p0x, $p0y);
else
$array = array($vx0, $vy0, $vx1, $vy1, $p3x, $p3y, $p0x, $p0y);
} else { // m>=0, q<0: basso
if ($vx1 == $max)
$array = array($vx0, $vy0, $vx1, $vy1, $p1x, $p1y);
else
$array = array($vx0, $vy0, $vx1, $vy1, $p2x, $p2y, $p1x, $p1y);
}
}
else // m < 0
if ($q >= 0) { // m < 0, q >= 0
if (! $cancella_sotto) { // m < 0, q >= 0: alto
if ($vx1 == $max)
$array = array($vx0, $vy0, $vx1, $vy1, $p2x, $p2y, $p3x, $p3y);
else
$array = array($vx0, $vy0, $vx1, $vy1, $p1x, $p1y, $p2x, $p2y, $p3x, $p3y);
} else { // m < 0, q >= 0: basso
if ($vx1 == $max)
$array = array($vx0, $vy0, $vx1, $vy1, $p1x, $p1y, $p0x, $p0y);
else
$array = array($vx0, $vy0, $vx1, $vy1, $p0x, $p0y);
}
} else { // m, q < 0
if (! $cancella_sotto) { // m>=0, q<0: alto
if ($vx1 == $max)
$array = array($p0x, $p0y, $px1, $py1, $p2x, $p2y, $p3x, $p3y, $p4x, $p4y);
}
}
if (isset ($array)) {
for ($i=0; $i < count ($array);) {
$array[$i] = $this->map_x ($array[$i++], $scale);
$array[$i] = $this->map_y ($array[$i++], $scale);
}
imagefilledpolygon($this->image, $array, count ($array) / 2, $col);
unset ($array);
}
}
}
class grafico extends gf_cartesiano {
var $basename;
var $middlename;
var $extension = ".png";
var $vertici;
var $grad_x;
var $grad_y;
Function grafico ($_a, $_b, $_c, $lge, $cambia_segno_gradiente, $name)
{
/* sostituisci in $a, $b, $c i valori agli oggetti frazione */
for ($i=1; $i < count ($_b)+1; $i++) {
$b[$i] = $_b[$i]->value();
for ($j=1; $j < 3; $j++)
$a[$i][$j] = $_a[$i][$j]->value();
}
for ($j=1; $j < 3; $j++)
$c[$j] = $_c[$j]->value();
if ($cambia_segno_gradiente) {
$this->grad_x = -$c[1];
$this->grad_y = -$c[2];
} else {
$this->grad_x = $c[1];
$this->grad_y = $c[2];
}
$this->basename = $name;
$this->image = $this->gf_cartesiano ($asse_x, $asse_y);
$this->fq_col($this->yellow);
$this->trova_vertici($a, $b, $vertici);
$max = $this->cerca_max($vertici)*1.1;
if ($asse_x >= $asse_y)
$asse_max = $asse_x;
else
$asse_max = $asse_y;
$this->scale = $asse_max / $max;
for ($i=1; $i < count ($b)+1; $i++)
$this->plotta_disequazione($a[$i][1], $a[$i][2], $b[$i], $lge[$i], $this->scale, $this->white);
for ($i=1; $i < count ($b)+1; $i++)
$this->plotta_disequazione($a[$i][1], $a[$i][2], $b[$i], "=", $this->scale, $this->blue);
$this->gradiente();
$this->assi($vertici, $this->scale);
$name = $this->basename . $this->extension;
$this->ping($name);
return $this->image;
}
Function gradiente ()
{
// $this->freccia($this->scale, 0, 0, $this->grad_x, $this->grad_y, $this->magenta);
$this->freccia($this->scale, 0, 0, $this->grad_x, $this->grad_y, $this->red);
}
Function passo($xi, $yi, $xf, $yf, $passo, &$name)
{
$name = $this->basename . $passo;
$this->cerchio($this->scale, $xf, $yf, 6, $this->red);
$this->freccia($this->scale, $xi, $yi, $xf, $yf, $this->darkorange);
/* la perpendicolare al gradiente passante per xf, yf */
$this->plotta_disequazione($this->grad_x, $this->grad_y, ($xf*$this->grad_x+$yf*$this->grad_y), "=", $this->scale, $this->green);
$this->ping($name. ".png");
}
Function cerca_max(&$vertici)
{
$max = $vertici[0];
for ($i=1; $i<count($vertici); $i++)
if ($vertici[$i]>$max)
$max = $vertici[$i];
// $max e' il max fra le intercette e i valori di x e di y dei vertici
return $max;
}
Function trova_vertici($a, $b, &$vertici)
{
$m = count ($b);
// dove incidono le rette
for($k=0, $i=1; $i<$m+1; $i++)
for ($j=$i+1; $j<$m+1; $j++) {
// le x
if ( $a[$i][1]*$a[$j][2] != $a[$j][1]*$a[$i][2] )
$vertici[$k]= ( $a[$j][2]*$b[$i] - $a[$i][2]*$b[$j] ) /
( $a[$i][1]*$a[$j][2] -$a[$j][1]*$a[$i][2] );
else
$vertici[$k]=0;
$k++;
// le y
if ($a[$i][2]!=0)
$vertici[$k]=( $b[$i]-$a[$i][1]*$vertici[$k-1] ) / $a[$i][2];
else
$vertici[$k]=0;
$k++;
}
// aggiungiamo intersezioni con gli assi
for ($i=0; $i<$m+1; $i++) {
if ($a[$i][1] != 0)
$vertici[$k++] = $b[$i]/$a[$i][1];
else
$vertici[$k++]=0;
if ($a[$i][2] != 0)
$vertici[$k++] = $b[$i]/$a[$i][2];
else
$vertici[$k++]=0;
}
}
}
?>