Graficando Vectores con GD+PHP (2da parte)

Después de tanto hacerme pato con mi proyecto de física (Ni tan solo, se supone era en equipo.), lo he terminado. Aunque, no literalmente, faltaron muchos detalles. No sabía que tuviera que presentarlo tan pronto, así que tuve que realizar alguna que otra acrobacia al mero estilo Microsoft parchando mi aplicación… obteniendo así un chilaquil medio funcional :P

A la aplicación solo se le da dos vectores, se elige forma en que el vector se introducirá, o sea modulo-ángulo, o simplemente por coordenadas y luego de esto darle en el botón intentar.

El formulario es un asco, lo hice exactamente dos horas antes de la presentación en público, jeje. Así que no acepto muchas críticas en esta parte jeje… En el código de la aplicación pues, valla que si duré bastante trabajando (Como cuatro sesiones creo).

Les dejo el código para que critiquen, y de igual forma la versión de demostración para apreciar bien el detalle final :D

  • El formulario para ingreso de datos.
  • El archivo que genera el plano cartesiano y tira los vectores.

    header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
    header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
    header('Content-type: image/png');
    //header("content-type: text/html");
     
    #Lax X son pares
    #Las Y son impares
     
    if(isset($_GET['V']))
        $V = $_GET['V'];
     
    if(!isset($_GET['angulo']) and !isset($_GET['modulo']) and !isset($_GET['V'])){
            $V[]=0;
            $V[]=0;
        }
     
     
    if(isset($_GET['modulo']) and isset($_GET['angulo']))//Si hay un angulo o módulo
        if(count($_GET['modulo'])!=count($_GET['angulo']))//deben coincidir en cantidad
            exit;//si no, termina la ejecución de la aplicación.
     
    //Evaluamos los vectores cuando estos vienen en la forma modulo angulo.
    if(isset($_GET['angulo']) and isset($_GET['modulo']))
        foreach($_GET['angulo'] as $k => $teta)
            if(!empty($teta)||!empty($_GET['modulo'][$k])){
                    $V[]= sprintf("%.1f",$_GET['modulo'][$k]*cos(deg2rad($teta)));//x
                    $V[]= sprintf("%.1f",$_GET['modulo'][$k]*sin(deg2rad($teta)));//y
                }
     
    /* Evaluamos la resultante */
     
    if(isset($_GET['operacion']) and $_GET['operacion']=="sumar"){
            $resultante_x=0;
            $resultante_y=0;
            foreach($V as $k => $v){
                    if($k%2==0)
                        $resultante_x += $v;
                    if($k%2!=0)
                        $resultante_y += $v;
                }
            $V[]=$resultante_x;
            $V[]=$resultante_y;
        }
    if(isset($_GET['operacion']) and $_GET['operacion']=="multiplicar"){
            if(count($V)>=2 and isset($_GET['valor']) and is_numeric($_GET['valor'])){
                    $resultante_x=$V[0]*$_GET['valor'];
                    $resultante_y=$V[1]*$_GET['valor'];
                    $V[]=$resultante_x;
                    $V[]=$resultante_y;
                }
        }
     
    //Agregamos un nuevo vector, que es la resultante.
     
    //Valores por default
    $ancho = 500;//Anchura de la imagen en pixeles
    $alto = 500;//Altura de la imagen en pixeles
    $d = 20;//Desplazamiento para el marco
    $cuadros_min = 5;//Cantidad mínima de cuadros permitiada.
    $ttf=1;//Tipo de fuente
     
    //Cantidad de cuadros por cada lado del plano cartesiano.
    $mayor_x = 0;
    $mayor_xn = 0;
    $mayor_y = 0;
    $mayor_yn = 0;
     
    //Obtenemos los valores de los extremos de cada lado del plano
    foreach($V as $k => $v){
            //Las X
            if($k%2==0){
                    if($v>0 and $v>$mayor_x)
                        $mayor_x = $v;
                    if($v&lt;0 and $v< $mayor_xn)
                        $mayor_xn = $v;
                }
            //Las Y
            if($k%2!=0){
                    if($v>0 and $v>$mayor_y)
                        $mayor_y = $v;
                    if($v&lt;0 and $v< $mayor_yn)
                        $mayor_yn = $v;
                }
        }
     
    $mayor_xn = abs($mayor_xn);//Mayor en X negativo
    $mayor_yn = abs($mayor_yn);//Mayor en Y negativo
     
    $img = imagecreatetruecolor($ancho,$alto);
    $img_ucol= imagecreatefromgif("aguila.gif");
     
    //Colores
    $blanco = imagecolorallocate($img,0xff,0xff,0xff);
    $negro = imagecolorallocate($img,0x0,0x0,0x0);
    //$gris = imagecolorallocate($img,0xe7,0xe7,0xe7);
    $gris = imagecolorallocate($img,0xdf,0xdf,0xdf);
    $rojo = imagecolorallocate($img,0xff,0x00,0x00);
    $dark_gray = imagecolorallocate($img,0xc5,0xc5,0xc5);
     
    //Creamos fondo de color blanco
    imagefilledrectangle($img,0,0,$ancho-1, $alto-1, $blanco);
     
    imagestring($img,2,$ancho-52,i(100),"Matus",$dark_gray);
    imagestring($img,2,$ancho-52,i(90),"Noemi",$dark_gray);
    imagestring($img,2,$ancho-70,i(80),"Renteria",$dark_gray);
    imagestring($img,2,$ancho-65,i(70),"Antonio",$dark_gray);
    imagestring($img,2,$ancho-64,i(60),"Roberto",$dark_gray);
    imagestring($img,2,$ancho-76,i(50),"Alexander",$dark_gray);
    imagestring($img,2,$ancho-60,i(40),"Victor",$dark_gray);
    //Si la orientación del mayor es en X (ox=true), tomamos comom referencia el ancho, si no, lo alto.
    if(($mayor_x+$mayor_xn)>($mayor_y+$mayor_yn))
            $ox = true;
        else
            $ox = false;
     
    if($ox){//Orientación en X
            $cuadros = $mayor_x+$mayor_xn;//Cantidad de cuadros
            if($cuadros != 0)
                    if($cuadros > $cuadros_min)
                            $cuadro_w = ($ancho-($d*2))/$cuadros;//Dimensiones por cuadro
                        else
                            $cuadro_w = ($ancho-$d*2)/$cuadros_min;
                else//Si solo hubiese un punto y en la coordenada 0,0 ocurriría un error de tipo "división by zero".
                    $cuadro_w = ($ancho-$d)/$cuadros_min; 
        }else{
            $cuadros = $mayor_y+$mayor_yn;//Cantidad de cuadros
            if($cuadros != 0)
                    if($cuadros > $cuadros_min)
                            $cuadro_w = ($alto-($d*2))/$cuadros;//Dimensiones por cuadro
                        else
                            $cuadro_w = ($alto-$d*2)/$cuadros_min;
                else//Si solo hubiese un punto y en la coordenada 0,0 ocurriría un error de tipo "división by zero".
                    $cuadro_w = ($alto-$d)/$cuadros_min;
        }
     
    $cuadro_w = floor($cuadro_w); //Entre más pequeño mejor.
     
    //Líneas verticales
    for($x=0;$x< $ancho;$x++)
        if($x%$cuadro_w==0)
            imageline($img,/*x1,y1*/$x+$d,i($alto),/*x2,y2*/$x+$d,i(1+$d),$gris);
     
    //Líneas horizontales
    for($y=0;$y<$alto;$y++)
        if($y%$cuadro_w==0)
            imageline($img,/*x1,y1*/1+$d,i($y+$d),/*x2,y2*/$ancho,i($y+$d),$gris);
     
    //Guías horizontales
    for($x=($mayor_xn*$cuadro_w*-1);$x<$ancho;$x++)
        if($x%$cuadro_w==0)
            imageline($img,/*x1,y1*/$x+$d,i(0+($mayor_yn*$cuadro_w)-2+$d),/*x2,y2*/$x+$d,i(2+($mayor_yn*$cuadro_w)+$d),$negro);
     
    //Guías verticales
    for($y=($mayor_yn*$cuadro_w*-1);$y<$alto;$y++)
        if($y%$cuadro_w==0)
            imageline($img,/*x1,y1*/0+($mayor_xn*$cuadro_w)-2+$d,i($y+$d),/*x2,y2*/2+($mayor_xn*$cuadro_w)+$d,i($y+$d),$negro);    
     
    //Se dibuja Plano cartesiano
    //Eje de Y
    imageline($img,/*x1,y1*/0+($mayor_xn*$cuadro_w)+$d,i(0+$d),/*x2,y2*/0+($mayor_xn*$cuadro_w)+$d,i($alto),$negro);
    //Eje de X
    imageline($img,/*x1,y1*/0+$d,i(0+$d)-($mayor_yn*$cuadro_w),/*x2,y2*/$ancho,i(0+$d)-($mayor_yn*$cuadro_w),$negro);
     
    //Cuadro de relleno para tapar Abajo e Izquierda.
    imagefilledrectangle($img,0,0,$d,$alto,$blanco);//izquierda
    imagefilledrectangle($img,0,$alto-$d,$ancho,$alto,$blanco);//abajo
     
    //Numeración vertical
    for($x=($mayor_xn*$cuadro_w*-1);$x<$ancho;$x++)
        if($x%$cuadro_w==0)
                if(floor($x/$cuadro_w)>=0)
                        imagestring($img,$ttf,$x+($mayor_xn*$cuadro_w)-imagefontwidth($ttf)*strlen(floor($x/$cuadro_w))+$d,i(($mayor_yn*$cuadro_w)-1+$d),floor($x/$cuadro_w),$negro);
                    else
                        imagestring($img,$ttf,$x+($mayor_xn*$cuadro_w)-2+$d,i(($mayor_yn*$cuadro_w)-1+$d),floor($x/$cuadro_w),$negro);
     
    //Numeración horizontal
    for($y=($mayor_yn*$cuadro_w*-1);$y< $alto;$y++)
        if($y%$cuadro_w==0)
            if(floor($y/$cuadro_w)>0)
                    imagestring($img,$ttf,($mayor_xn*$cuadro_w)+$d-imagefontwidth($ttf)*strlen(floor($y/$cuadro_w)),i($y+$d)-($mayor_yn*$cuadro_w)+1,floor($y/$cuadro_w),$negro);
                elseif(floor($y/$cuadro_w)&lt;0)
                    imagestring($img,$ttf,($mayor_xn*$cuadro_w)+$d-imagefontwidth($ttf)*strlen(floor($y/$cuadro_w)),i($y+$d+10)-($mayor_yn*$cuadro_w)+1,floor($y/$cuadro_w),$negro);
     
    //Cuadro de relleno para tapar arriba y derecha.
    imagefilledrectangle($img,0,0,$ancho,$d,$blanco);//arriba
    imagefilledrectangle($img,$ancho-$d,$d,$ancho,$alto,$blanco);//derecha
     
    imageline($img,$d,$d,$ancho-$d,$d,$negro);//arriba
    imageline($img,$d,$alto-$d,$ancho-$d,$alto-$d,$negro);//abajo
    imageline($img,$ancho-$d,$d,$ancho-$d,$alto-$d,$negro);//derecha
    imageline($img,$d,$d,$d,$alto-$d,$negro);//izquierda
     
    //Tiramos los vectores
        foreach($V as $k => $v){
                if($k%2==0)
                    $x=$v;
                if($k%2!=0)
                    vector($x,$v,$negro);
            }
     
    //Tiramos líneas del paralelogramo
        if(isset($_GET['operacion']) and $_GET['operacion']=="sumar" and isset($V[5])){
                linea($V[0],$V[1],$V[4],$V[5],$gris);
                linea($V[2],$V[3],$V[4],$V[5],$gris);
            }
     
    if(isset($_GET['operacion']) and $_GET['operacion']=="restar" and count($V)>=4){
            linea($V[0],$V[1],$V[2],$V[3],$negro,true);
        }
     
    //resultante
        if(isset($_GET['operacion']) and $_GET['operacion']=="sumar")
            linea(0,0,$resultante_x,$resultante_y,$negro,true);
     
     
        if(isset($_GET['operacion']) and $_GET['operacion']=="multiplicar")
            if(isset($_GET['valor']) and is_numeric($_GET['valor']))
                    linea(0,0,$resultante_x,$resultante_y,$negro,true);
                else{
                        $rosa = imagecolorallocate($img,0xff,0xd7,0xff);
                        imagefilledrectangle($img,30,240,470,274,$rosa);
                        imagestring($img,3,40,250,"Para multiplicar, es necesario un solo vector, y un escalar.",$rojo);
                    }
     
    //Nombre aleatoreo para la imagen
    $imagen = "img/".time()."-".rand(100,999).".png";
    $imagen = "temp.png";
     
    imagefilter($img,IMG_FILTER_NEGATE);
     
    //Logotipo de la Universidad de Colima
    imagecopyresampled($img,$img_ucol,$ancho-36,8,0,0,30,30,268,267);
     
    //imagepng($img,$imagen);//Para el Historial
    imagepng($img);//La mostramos
    imagedestroy($img);//Liberamos la memoria
     
    function vectores($V){
            foreach($V as $k => $v){
                    if($k%2==0)
                        echo "(";
     
                    if($k%2==0)
                            echo "<span style='color:#f00;'>$v</span>";
                        else
                            echo "$v";
     
                    if($k%2==0)
                            echo ",";
                        else
                            echo ")<br />";
                }
        }
     
    function ordenar($V){
            $N = count($V)-1;
            for($i=1;$i< =$N;$i++){
                    if($i%2!=0)continue;//si es Y, continue;
                    //Solo X
                    for($j=$N;$j>=$i;$j--){
                            if($j%2!=0)continue;//si es Y, continue;
                            //Solo X
                            if($V[$j-2]>$V[$j]){
                                    $aux = $V[$j-2];
                                        $aux2 = $V[$j-1];
                                    $V[$j-2] = $V[$j];
                                    $V[$j-1] = $V[$j+1];
     
                                    $V[$j] = $aux;
                                    $V[$j+1] = $aux2;
                                }
                        }
                }
            return $V;
        }
     
    function i($x){//Invierte los valores
            global $alto;
            return $alto-$x;        
        }
     
    function vector($x,$y,$color=""){//Tira un Vector en el plano
            global $img, $cuadro_w, $mayor_xn, $d, $mayor_yn, $negro;
            $blanco = imagecolorallocatealpha($img,0xff,0xff,0xff,40);
            $ttf = 2;//Tamaño de la fuente
     
            if(empty($color)){
                    $r = rand(0,200);
                    $g = rand(0,250);
                    $b = rand(0,200);
                    $color = imagecolorallocate($img,$r,$g,$b);
                }
     
            $Acolor = $color;//imagecolorallocate($img,$b,0,$r);
     
            //Equivalente a Coordenada 0
            $x0 = $cuadro_w * $mayor_xn + $d;
            $y0 = $cuadro_w * $mayor_yn + $d;
     
            //Punto donde termina el vector
            $xf = $x0 + ($cuadro_w * $x);
            $yf = $y0 + ($cuadro_w * $y);
     
            $A="($x,$y)";
            $Aw = imagefontwidth($ttf) * strlen($A);
            $Ah = imagefontheight($ttf);
     
            //Tiramos Línea
            imageline($img,$x0,i($y0),$xf,i($yf),$color);
     
            //angulo del vector
     
     
            //Dibujamos las coordenadas
            if(!($x==0||$y==0)){
                if($x>0 and $y>0){
                        imagefilledrectangle($img,$xf-$Aw,i($yf),$xf-$Aw+$Aw-1,i($yf)+$Ah-1,$blanco);
                        imagestring($img,$ttf,$xf-$Aw,i($yf),$A,$negro);
                    }
                if($x&lt;0 and $y>0){
                        imagefilledrectangle($img,$xf+imagefontwidth($ttf)* 2,i($yf),$xf+imagefontwidth($ttf)*2+$Aw-1,i($yf)+$Ah-1,$blanco);
                        imagestring($img,$ttf,$xf+imagefontwidth($ttf)* 2,i($yf),$A,$Acolor);
                    }
                if($x&lt;0 and $y&lt;0){
                        imagefilledrectangle($img,$xf+imagefontwidth($ttf)* 2,i($yf+$Ah),$xf+imagefontwidth($ttf)*2+$Aw-1,i($yf+$Ah)+$Ah-1,$blanco);
                        imagestring($img,$ttf,$xf+imagefontwidth($ttf)* 2,i($yf+$Ah),$A,$Acolor);
                    }
                if($x>0 and $y&lt;0){
                        imagefilledrectangle($img,$xf-$Aw-imagefontwidth($ttf)* 2,i($yf+$Ah),$xf-$Aw-imagefontwidth($ttf)*2+$Aw-1,i($yf+$Ah)+$Ah-1,$blanco);
                        imagestring($img,$ttf,$xf-$Aw-imagefontwidth($ttf)* 2,i($yf+$Ah),$A,$Acolor);
                    }
            }else{
                    if($y==0 and $x>0){
                            imagefilledrectangle($img,$xf+imagefontwidth($ttf),i($yf+$Ah),$xf+imagefontwidth($ttf)+$Aw-1,i($yf+$Ah)+$Ah-1,$blanco);
                            imagestring($img,$ttf,$xf+imagefontwidth($ttf),i($yf+$Ah),$A,$Acolor);
                        }
                    if($x==0 and $y>0){
                            imagefilledrectangle($img,$xf+imagefontwidth($ttf),i($yf),$xf+imagefontwidth($ttf)+$Aw-1,i($yf)+$Ah-1,$blanco);
                            imagestring($img,$ttf,$xf+imagefontwidth($ttf),i($yf),$A,$Acolor);
                        }
                    if($y==0 and $x&lt;0){
                            imagefilledrectangle($img,$xf+imagefontwidth($ttf),i($yf+$Ah),$xf+imagefontwidth($ttf)+$Aw-1,i($yf+$Ah)+$Ah-1,$blanco);
                            imagestring($img,$ttf,$xf+imagefontwidth($ttf),i($yf+$Ah),$A,$Acolor);
                        }
                    if($x==0 and $y&lt;0){
                            imagefilledrectangle($img,$xf+imagefontwidth(