immagini.php

<?php
declare(strict_types=1);

class gf_cartesiano
{
	// dimensioni immagine totale
	public int $_x_size_;
	public int $_y_size_;
	// coordinate origine assi
	public int $_x0_;
	public int $_y0_;
	// dimensioni asse x
	public int $_xi_;
	public int $_xf_;
	public int $_x_axis_;
	// dimensioni asse y
	public int $_yi_;
	public int $_yf_;
	public int $_y_axis_;
	// l'immagine
	public GdImage $image;
	// qualche colore
	public readonly int $white;
	public readonly int $black;
	public readonly int $red;
	public readonly int $blue;
	public readonly int $green;
	public readonly int $magenta;
	public readonly int $yellow;
	public readonly int $darkgreen;
	public readonly int $darkorange;
	// settata nel costruttore, ma non usata
	public float|int $scale;

	public function __construct(float|int &$x_axis, float|int &$y_axis)
		// costruttore
	{
		// settta le dimensioni dell'immagine
		$this->_x_size_ = 480; // 480;
		$this->_y_size_ = 480; // 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 = imagecreatetruecolor($this->_x_size_, $this->_y_size_);
		// alloca i colori
		$this->white = (int)ImageColorAllocate($this->image, 255, 255, 255);
		$this->black = (int)ImageColorAllocate($this->image, 0, 0, 0);
		//$this->red = ImageColorAllocate($this->image, 255, 0, 0);
		$this->red = (int)ImageColorAllocate($this->image, 127, 0, 0);
		$this->green = (int)ImageColorAllocate($this->image, 0, 255, 0);
		$this->blue = (int)ImageColorAllocate($this->image, 0, 0, 255);
		$this->magenta = (int)ImageColorAllocate($this->image, 255, 0, 255);
		$this->yellow = (int)ImageColorAllocate($this->image, 255, 255, 0);
		$this->darkgreen = (int)ImageColorAllocate($this->image, 0, 100, 0);
		//$this->darkorange = ImageColorAllocate($this->image, 255, 127, 0);
		$this->darkorange = (int)ImageColorAllocate($this->image, 255, 63, 63);
		// assegna un valore a caso a scale
		$this->scale = 1;
		// ritorna il puntatore all'immagine
		// return $this->image;
	}

	public function fq_col(int $col): void
		// colora il primo quadrante
	{
		$tile = imageCreateFromPNG('images/regione_amm.png');
		if (!$tile) {
			die ('Unable to open image');
		}
		imageSetTile($this->image, $tile);
		imagefilledrectangle($this->image, 0, 0, $this->_x_size_, $this->_y_size_, $this->white);
		imagefilledrectangle($this->image, 30, 20, $this->_x_size_ - 20, $this->_x_size_ - 30, IMG_COLOR_TILED);
	}

	/** @param array<int, float|int> $vertici */
	public function assi(array $vertici, float|int $scale): void
		// 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, (int)$x, $this->_y0_, (int)$x, $this->_y0_ + 5, $this->black);
			if (abs(floor($vertici[$i]) - $vertici[$i]) <= 0.00001) $lettere = sprintf("%d", $vertici[$i]);
			else $lettere = sprintf("%.2f", $vertici[$i]);
			imagestring($this->image, 3, (int)$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, (int)$y, $this->_x0_, (int)$y, $this->black);
			if (abs(floor($vertici[$i]) - $vertici[$i]) <= 0.00001) $lettere = sprintf("%d", $vertici[$i]);
			else $lettere = sprintf("%.2f", $vertici[$i]);
			imagestring($this->image, 3, $this->_x0_ - 30, (int)$y, $lettere, $this->black);
		}
	}

	public function map_x(float|int $vx, float|int $scale): int
		/* ritorna il valore della coordinata x sull'immagine corrispondente al punto
		 di coordinata vx nell'asse cartesiano, fissato il parametro di scala */
	{
		return (int)($this->_x0_ + round($scale * $vx));
	}

	public function map_y(float|int $vy, float|int $scale): int
		/* ritorna il valore della coordinata y sull'immagine corrispondente al punto
		 di coordinata vy nell'asse cartesiano, fissato il parametro di scala */
	{
		return (int)($this->_y0_ - round($scale * $vy));
	}

	public function freccia(float|int $scale, float|int $vxi, float|int $vyi, float|int $vxf, float|int $vyf, int $col): void
		/* 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
		*/
		$xr = 0;
		$yr = 0;
		$xs = 0;
		$ys = 0;
		// 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;
		$sin_ = $y / $modulo;
		$cos_ = $x / $modulo;
		// calcola gli estremi dei segmenti delle frecce
		// r rotazione di 45deg 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, (int)$xi, (int)$yi, (int)$xf, (int)$yf, $col);
		imageline($this->image, (int)$xi - 1, (int)$yi, (int)$xf - 1, (int)$yf, $col);
		imageline($this->image, (int)$xi + 1, (int)$yi, (int)$xf + 1, (int)$yf, $col);
		imageline($this->image, (int)$xi, (int)$yi - 1, (int)$xf, (int)$yf - 1, $col);
		imageline($this->image, (int)$xi, (int)$yi + 1, (int)$xf + 1, (int)$yf + 1, $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);
		return;
	}

	public function ruota(float|int $x, float|int $y, float|int &$xr, float|int &$yr, float $alpha): void
		// ruota (x, y)-(0, 0) di un angolo alpha
	{
		$xr = $x * cos($alpha) - $y * sin($alpha);
		$yr = $y * cos($alpha) + $x * sin($alpha);
	}

	public function cerchio(float|int $scale, float|int $vx0, float|int $vy0, float|int $l, int $col): void
		/* 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);
		imagefilledrectangle($this->image, (int)($x0 - 3 * $l2 / 2), (int)($y0 - 3 * $l2 / 2), (int)($x0 + 3 * $l2 / 2), (int)($y0 + 3 * $l2 / 2), $col);
	}

	public function ping(string $name): void
		// scrive l'immagine in formato PNG nel file di nome $name
	{
		imagepng($this->image, $name);
	}

	public function plotta_disequazione(float|int $ax, float|int $ay, float|int $b, string $lge, float|int $scale, int $col): int
		/* disegna i segmenti corrispondenti alla dis/equazione immessa 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; // (sx,basso)
		$vx0 = 0;
		$vx1 = 0;
		$vy0 = 0;
		$vy1 = 0;
		$a = 0;
		$bTmp = 0;
		$array1 = [];
		$p1x = $max;
		$p1y = 0; // (dx,basso)
		$p2x = $max;
		$p2y = $max; // (dx, alto)
		$p3x = 0;
		$p3y = $max; // (sx, alto)
		$p4x = 0;
		$p4y = 0;

		if ($ax == 0) { // ay y = b
			if ($ay == 0) return 0;
			$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;
		//    echo "<br /> y = " . $m . "x + " . $q . "<br />\n";
		//    echo "<br /> cancella_sotto = " . (bool)(isset($cancella_sotto) && $cancella_sotto) . "<br />\n";
		//    echo "<br /> isset(cancella_sotto) = " . isset($cancella_sotto) . "<br />\n";
		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, $p1x, $p1y, $p2x, $p2y, $p3x, $p3y, $p4x, $p4y);
				}
			}
		if (isset($array)) {
			for ($i = 0; $i < count($array);) {
				$array1[$i] = $this->map_x($array[$i], $scale);
				$array1[$i + 1] = $this->map_y($array[$i + 1], $scale);
				//imagearc($this->image, $array1[$i], $array1[$i+1],1,1,0,360,$this->blue);
				$i += 2;
			}
			imagefilledpolygon($this->image, $array1, (int)(count($array1) / 2), $col);
			unset($array);
			unset($array1);
		}
		return 0;
	}

	public function line(float|int $scale, float|int $vxi, float|int $vyi, float|int $vxf, float|int $vyf, int $col): void
		/* 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, (int)$xi, (int)$yi, (int)$xf, (int)$yf, $col);
		imageline($this->image, (int)$xi - 1, (int)$yi, (int)$xf - 1, (int)$yf, $col);
		imageline($this->image, (int)$xi + 1, (int)$yi, (int)$xf + 1, (int)$yf, $col);
		imageline($this->image, (int)$xi, (int)$yi - 1, (int)$xf, (int)$yf - 1, $col);
		imageline($this->image, (int)$xi, (int)$yi + 1, (int)$xf, (int)$yf + 1, $col);
	}
}

class grafico extends gf_cartesiano
{
	public string $basename;
	public string $baseurl;
	public string $middlename;
	public string $extension = ".png";
	/** @var array<int, float|int> */
	public array $vertici;
	public float $grad_x;
	public float $grad_y;

	/**
	 * @param array<mixed> $_a
	 * @param array<mixed> $_b
	 * @param array<mixed> $_c
	 * @param array<mixed> $lge
	 */
	public function __construct(array $_a, array $_b, array $_c, array $lge, bool $cambia_segno_gradiente, string $name, string $urlname = "")
	{
		$asse_x = 0;
		$asse_y = 0;
		$a = [];
		$b = [];
		parent::__construct($asse_x, $asse_y);
		/* 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->baseurl = $urlname !== "" ? $urlname : $name;
		// $this->image = $this->gf_cartesiano ($asse_x, $asse_y);
		$this->fq_col($this->yellow);
		$vertici = array();
		$this->trova_vertici($a, $b, $vertici);
		$max = $this->cerca_max($vertici) * 1.1;
		$this->scale = $asse_x / $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);
			//        $this->ping($name . "___"  $i);

		}
		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);
		$filename = $this->basename . $this->extension;
		$this->ping($filename);
	}

	/**
	 * @param array<mixed> $a
	 * @param array<mixed> $b
	 * @param array<int, float|int> $vertici
	 */
	public function trova_vertici(array $a, array $b, array &$vertici): void
	{
		// numero di equazioni
		$m = count($b);
		$vertici = array_fill(0, (int)(($m * $m + 3 * $m) / 2 + 1), 0);
		// 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++;
			// echo "$i &cap; $j = (" . $vertici[$k-2] . ", " . $vertici[$k - 1] . ") <br />\n";

		}
		// aggiungiamo intersezioni con gli assi
		for ($i = 1; $i < $m + 1; $i++) {
			if (!isset($a[$i][1]) || $a[$i][1] != 0) {
				$vertici[$k++] = $b[$i] / $a[$i][1];
				$vertici[$k++] = 0;
			} //else {
			//    $vertici[$k++]=0;
			// echo "$i &cap; _0_ = (" . $vertici[$k-2] . ", " . $vertici[$k - 1] . ") <br />\n";
			if (!isset($a[$i][2]) || $a[$i][2] != 0) {
				$vertici[$k++] = 0;
				$vertici[$k++] = $b[$i] / $a[$i][2];
			} // else
			//    $vertici[$k++]=0;
			// echo "_0_ &cap; $i = (" . $vertici[$k-2] . ", " . $vertici[$k - 1] . ") <br />\n";

		}
	}

	/** @param array<int, float|int> $vertici */
	public function cerca_max(array &$vertici): float|int
	{
		$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;
	}

	public function gradiente(): void
	{
		$this->freccia($this->scale, 0, 0, $this->grad_x, $this->grad_y, $this->magenta);
	}

	public function passo(float|int $xi, float|int $yi, float|int $xf, float|int $yf, int $passo, string &$name): void
	{
		$filename = $this->basename . $passo;
		$name = $this->baseurl . $passo;
		/* 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->darkgreen);
		$this->cerchio($this->scale, $xf, $yf, 6, $this->red);
		$this->freccia($this->scale, $xi, $yi, $xf, $yf, $this->darkorange);

		$this->ping($filename . ".png");
		$this->gradiente();
		$this->cerchio($this->scale, $xf, $yf, 6, $this->red);
	}
}