Basic tools for analyze PHP Code

If you get enrollment into a new work to maintain  Php project with millions of thousands of  lines of code written these tools can be one of your best friends.

phploc: phploc is a tool for quickly measuring the size of a PHP project.

install on fedora 15:

su

yum install php-phpunit-phploc.noarch

usage:

phploc <php source code dir>

phpdcd: phpdcd is a Dead Code Detector (DCD) for PHP code. It scans a PHP project for code that is no longer used.

install on fedora 15:

su

yum install php-phpunit-phpdcd.noarch

usage:

phpdcd  <php source code dir>

phpcpd: phpcpd is a Copy/Paste Detector (CPD) for PHP code. It scans a PHP project for duplicated code.

install on fedora 15:

su

yum install php-phpunit-phpcpd.noarch

usage:

phpcpd <php source code dir>

if your project is enormous you will need another key tools: Hope, Faith and Hard Work

more info about these tools and more at http://sebastian-bergmann.de/software/

Using Logical Or in Perl regex


#!/usr/bin/perl

use strict;
use warnings;

my %colors=( "life" , "white or black",
 "cat" , "black",
 "horse" , "white or black",
 "blood",    "red",
 "sky" ,"blue");

foreach my $coloredThing (keys %colors)
{
 print "$coloredThing ";
 if ($colors{$coloredThing}=~m/(black|white)/)
 {
 print "Match";
 }
 else
 {
 print "Doesn't Match";
 }
 print "\n";
}

and here the Output

sky Doesn’t Match
blood Doesn’t Match
cat Match
horse Match
life Match

Associative Arrays in Bash v4

One of the new features in Bash v4 are the associative arrays using strings as index instead numbers
here a small example of use


#!/bin/bash

declare -A myArray #declare array
myArray[cat]=gato #attach a value into index cat
myArray[dog]=can #attach a value into index dog

creature="fish" #declare a variable

myArray[$creature]=peixe #attach a value into index fish

#get all array values
for key in "${!myArray[@]}"
 do
 echo "index value=$key content value= ${myArray[$key]}"
 done

Informática Gráfica PRÁCTICA 4. Transformaciones geométricas.

EJERCICIOS

Inicialmente debes construir un nuevo proyecto (practica4). Una vez creado, copia en el directorio de trabajo los ficheros examinar.c, examinar.h y la librería creada en la práctica anterior glig.c con su fichero prototipo glig.h. Añádelos al proyecto (por supuesto, acuérdate de añadir también las librerías glu32.lib, glut.lib y opengl32.lib).

1. Para la realización de esta práctica vas a necesitar una nueva primitiva que dibuje un cono. Añádela a tu librería glig.c.

void igWireCone (int pu, int pv); /* s1= 2.0, s2= 1.0, uMax= 1.0, vMax= 0.5 */

2. Utiliza las primitivas de la librería glig.c, para construir un abeto como el de la figura, sin utilizar las funciones glPushMatrix() y glPopMatrix(). Para ello crea una display list como en el ejemplo e introduce en su definición el código necesario para dibujar el abeto:

void CreaAbeto (void)

{

abeto = glGenLists (1);

if (abeto != 0) /* Cero no es un identificador valido para una display list */

{

glNewList (abeto, GL_COMPILE);

/* Código para dibujar el abeto */

glEndList ();

}

}

Los pasos a seguir para dibujar el abeto son:

  1. Dibuja el primer cono con los siguientes factores de escala: Sx=0.75 Sy=1.0 Sz=0.75.
  2. A continuación, dibuja dos nuevos conos aplicando los mismos factores de escala y trasladándolos sobre el eje Y, Tx=0.0 Ty=0.25 Tz= 0.0.
  3. Finalmente, dibuja el tronco llamando a la función igWireRulo(int pu, int pv).

Desde la función principal (main) debes llamar una única vez a CreaAbeto(). Para dibujar el abeto como una display list, llama desde la función Dibuja() a:
glCallList (abeto);

3. Construye el mismo abeto pero mediante el uso de las funciones  glPushMatrix() y glPopMatrix(). Es decir, haz que cada primitiva tenga sus transformaciones propias y que estas no afecten a las otras primitivas. Declara una nueva display list (abetoPush) y crea la display list para dibujar el abeto con las funciones glPush() y glPop() y llámala CreaAbetoPush().Comprueba que los dos abetos son iguales dibujando uno sobre otro con distintos colores.

4. Utilizando las primitivas de la librería glig.c, construye una display list para una escalera de caracol (escalera). Introduce el código en la función CreaEscalera(). Los pasos son los siguientes:

  1. Dibuja una caja a modo de eje de la escalera de altura=2.0 y lado= 0.2
  2. Realiza un bucle para dibujar cada uno de los escalones. Los escalones están escalados con factores de escala, Sx=0.5 Sy= 0.05 Sz=0.1. La separación entre escalones es de 0.2.

5. Realiza la construcción de la figura (lo más parecida posible) de acuerdo con los siguientes pasos:

  1. En primer lugar define una función Arco() que construya un arco individual (con tres cajas)
  2. Utiliza ese elemento para realizar la construcción circular.

modelado abetomodelado abeto pushmodelado escaleramodelado patioexaminar.c


/*************************************************************************/
/*                                                                       */
/*   examinar.c                                                          */
/*   Rev. 2.0  01/01/2002   AUTORES: O. Belmonte, M. Chover, J. Ribelles */
/*                                                                       */
/*************************************************************************/

/***************** INCLUDES DE LAS LIBRERIAS NECESARIAS ******************/
#include &lt;GL/glut.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &quot;examinar.h&quot;
#include &quot;glig.h&quot;

/******************************************************************************************/
/* Establece el area visible y el tipo de proyeccion                                      */
/* Parametros: int ancho --&gt; Ancho del area visible                                       */
/*             int alto --&gt; Alto del area visible                                         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void TamanyoVentana (GLsizei ancho, GLsizei alto)
{
 /* Definicion del viewport */
 glViewport(0, 0, ancho, alto);

 /* Definicion de la vista */
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glOrtho(-2.0, 2.0, -2.0*(GLfloat)alto/(GLfloat)ancho, 2.0*(GLdouble)alto/(GLfloat)ancho, -2.0, 2.0);
}

/******************************************************************************************/
/* Abre una ventana OpenGL                                                                */
/* Parametros: int numeroArgumentos --&gt; El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --&gt; Vector de cadenas con cada argumento           */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void AbreVentana (int numeroArgumentos, char ** listaArgumentos)
{
 glutInit(&amp;numeroArgumentos, listaArgumentos);
 glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
 glutInitWindowSize (VentanaAncho, VentanaAlto);
 glutInitWindowPosition (VentanaX, VentanaY);
 glutCreateWindow (listaArgumentos[0]);
 glutDisplayFunc (Dibuja);
 glutReshapeFunc (TamanyoVentana);
 glClearColor (0.0f, 0.0f, 0.0f, 0.0f); /* Establece el color de borrado */
 glClear (GL_COLOR_BUFFER_BIT); /* Borra el buffer de color */
 glColor3f (1.0f, 1.0f, 1.0f); /* Establece el color de dibujo */
}

/******************************************************************************************/
/* Define las acciones tras una pulsacion del teclado                                     */
/* Parametros: unsigned char key --&gt; Codigo de la tecla pulsada                           */
/*             int x --&gt; Coordenada x del cursor en el momento de pulsar la tecla         */
/*             int y --&gt; Coordenada y del cursor en el momento de pulsar la tecla         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void Teclado (unsigned char tecla, int x, int y)
{
 switch (tecla)
 {
 case 27 : /* Codigo de la tecla de Escape */
 exit(0);
 break;
 }
}

/******************************************************************************************/
/* Define las acciones tras una pulsacion del teclado ampliado                            */
/* Parametros: unsigned char key --&gt; Codigo de la tecla pulsada                           */
/*             int x --&gt; Coordenada x del cursor en el momento de pulsar la tecla         */
/*             int y --&gt; Coordenada y del cursor en el momento de pulsar la tecla         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void TecladoAmpliado (int tecla, int x, int y)
{
 switch (tecla)
 {
 case GLUT_KEY_UP : /* Pulsacion cursor arriba del teclado ampliado */
 beta = beta + 15.0;
 if (beta &gt; 360.0) beta = beta - 360.0;
 break;

 case GLUT_KEY_DOWN : /* Pulsacion cursor abajo del teclado ampliado */
 beta = beta - 15.0;
 if (beta &lt; 0.0) beta = beta + 360.0;
 break;

 case GLUT_KEY_RIGHT : /* Pulsacion cursor derecha del teclado ampliado */
 alfa = alfa + 15.0;
 if (alfa &gt; 360.0) alfa = alfa - 360.0;
 break;

 case GLUT_KEY_LEFT : /* Pulsacion cursor izquierda del teclado ampliado */
 alfa = alfa - 15.0;
 if (alfa &lt; 0.0) alfa = alfa + 360.0;
 break;
 }
 glutPostRedisplay ();
}

/* Rutina de definiciÛn de eventos */
/******************************************************************************************/
/* Inicia las funciones de callback                                                       */
/* Parametros: Ninguno                                                                    */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void IniciaFuncionesCallback (void)
{
 glutKeyboardFunc (Teclado);
 glutSpecialFunc (TecladoAmpliado);
}

/******************************************************************************************/
/* Funcion de dibujado                                                                    */
/* Parametros: Ninguno                                                                    */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void Dibuja (void)
{
 glClear (GL_COLOR_BUFFER_BIT);

 /* Transformacion de la camara */
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
 glRotated (beta, 1.0,0.0,0.0);
 glRotated (-alfa, 0.0,1.0,0.0);

 glCallList (cuadrica);
 glCallList(abetoPush);
 glCallList (abeto);
 glCallList(escalera);
 glCallList(patio);

 /* Objetos */
 //glutWireTeapot(1.0);
 //glutWireIcosahedron();
 //glutWireTetrahedron();
 //glutWireOctahedron();
 //glutWireDodecahedron();
 //glutWireTorus(0.2,0.9,18,20);
 //glutWireCone(0.5, 2.0, 14, 14);
 //glutWireCube(1.0);
 //glutWireSphere(1, 20,50);

 //igCreateQuadricObject(50,80,0,0,1.0, 1, 1);
 //igWireSphere (50, 50);

 //igWireRulo (200, 200);
 //igWireDado (60, 60);
 //igWireSemiSphere (50, 50); // s1 y s2 a 1, uMax= 1, vMax= 0.5 */
 //igWireCubo();
 glFlush();
}

void IniciaCuadricas (void)
{
 cuadrica = glGenLists (1);
 escalera=glGenLists(1);
 abeto=glGenLists(1);
 abetoPush=glGenLists(1);
 patio=glGenLists(1);

 if (cuadrica != 0) /* Cero no es un identificador valido para una display list */
 {
 //glNewList (cuadrica, GL_COMPILE);
 //igCreateQuadricObject (20,20,0,0,1.0f, 1.0f, 1.0f);
 //igWireCubo();
 //igWireRulo(20, 20);
 //igWireCone(10,3);
 //igWireSphere(30, 30);
 //glEndList ();
 printf(&quot;Cuadratica\n&quot;);
 }
 if (escalera!=0)
 {
 //CreaEscalera();
 printf(&quot;Escalera\n&quot;);
 }
 if (abeto!=0)
 {
 //CreaAbeto();
 printf(&quot;Abeto\n&quot;);
 }
 if (abetoPush!=0)
 {
 glNewList(abetoPush, GL_COMPILE);
 //CreaAbetoPush();
 glEndList();
 printf(&quot;AbetoPush\n&quot;);
 }
 if (patio!=0)
 {

 CreaPatio();
 printf(&quot;patio\n&quot;);
 }

}

/******************************************************************************************/
/* Funcion principal                                                                      */
/* Parametros: int numeroArgumentos --&gt; El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --&gt; Vector de cadenas con cada argumento           */
/* Salida: Un entero que se devuelve al sistema al acabar la ejecucion del programa       */
/******************************************************************************************/
int main(int numArgumentos, char ** listaArgumentos)
{

 /* CreaciÛn de la ventana de la aplicaciÛn */
 AbreVentana (numArgumentos, listaArgumentos);

 /* Rutinas para el control de eventos */
 IniciaFuncionesCallback ();
 IniciaCuadricas();
 /* A la espera de eventos.... */
 glutMainLoop();
 return (0);
}

glig.c


/*************************************************************************/
/*                                                                       */
/*                 glig.c LIBRERIA DE MODELADO GEOMETRICO                 */
/*                                                                       */
/*   Rev. 2.0  01/01/2002   AUTORES: O. Belmonte, M. Chover, J. Ribelles */
/*                                                                       */
/*************************************************************************/

/***************** INCLUDES DE LAS LIBRERIAS NECESARIAS ******************/
#include &lt;GL/glut.h&gt;
#include &lt;math.h&gt;
#include &lt;stdio.h&gt;
#include &quot;glig.h&quot;

#define PI 3.1415926535897932
#define ALFA (0.5-v)*PI
#define BETA 2*PI*u

/************************* FUNCIONES BASICAS **********************************************/
/******************************************************************************************/
/* Devuelve la coordenada x de un punto en R3 a partir de un punto (u,v)                  */
/*   de un espacio parametrico en R2                                                      */
/* Parametros: float u --&gt; Primera coordenada de un punto en R2                           */
/*             float v --&gt; Segunda coordenada de un punto en R2                           */
/*             float R --&gt; Radio de la esfera envolvente                                  */
/*             float s1 --&gt; Numero de divisiones en u                                     */
/*             float s2 --&gt; Numero de divisiones en v                                     */
/* Salida: La coordenada x de un punto en R3                                              */
/******************************************************************************************/
float xSuperQuadric (float u, float v, float R, float s1, float s2)
{
 float cosalfa, cosbeta, powcosalfa, powcosbeta;

 cosalfa = (float)cos(ALFA);
 cosbeta = (float)cos(BETA);

 if(cosalfa &gt; 0.0)
 powcosalfa = (float)pow(cosalfa,s1);
 else
 powcosalfa =(float) - pow(- cosalfa,s1);

 if(cosbeta &gt; 0.0)
 powcosbeta = (float)pow(cosbeta,s2);
 else
 powcosbeta = (float) - pow(- cosbeta,s2);

 return (R*powcosalfa*powcosbeta);

}

/******************************************************************************************/
/* Devuelve la coordenada y de un punto en R3 a partir de un punto (u,v)                  */
/*   de un espacio parametrico en R2                                                      */
/* Parametros: float u --&gt; Primera coordenada de un punto en R2                           */
/*             float v --&gt; Segunda coordenada de un punto en R2                           */
/*             float R --&gt; Radio de la esfera envolvente                                  */
/*             float s1 --&gt; Numero de divisiones en u                                     */
/*             float s2 --&gt; Numero de divisiones en v                                     */
/* Salida: La coordenada y de un punto en R3                                              */
/******************************************************************************************/
float ySuperQuadric (float u, float v, float R, float s1, float s2)
{
 float sinalfa, powsinalfa;

 sinalfa = (float)sin(ALFA);

 if(sinalfa &gt; 0.0)
 powsinalfa = (float)pow(sinalfa,s1);
 else
 powsinalfa = (float)- pow(- sinalfa,s1);

 return (R*powsinalfa);
}

/******************************************************************************************/
/* Devuelve la coordenada de un punto en R3 a partir de un punto (u,v)                    */
/*   de un espacio parametrico en R2                                                      */
/* Parametros: float u --&gt; Primera coordenada de un punto en R2                           */
/*             float v --&gt; Segunda coordenada de un punto en R2                           */
/*             float R --&gt; Radio de la esfera envolvente                                  */
/*             float s1 --&gt; Numero de divisiones en u                                     */
/*             float s2 --&gt; Numero de divisiones en v                                     */
/* Salida: La coordenada z de un punto en R3                                              */
/******************************************************************************************/
float zSuperQuadric(float u, float v, float R, float s1, float s2)
{
 float cosalfa, sinbeta, powcosalfa, powsinbeta;

 cosalfa = (float)cos(ALFA);
 sinbeta=(float)sin(BETA);

 if(cosalfa &gt; 0.0)
 powcosalfa = (float)pow(cosalfa,s1);
 else
 powcosalfa=(float) - pow(- cosalfa,s1);

 if(sinbeta &gt; 0.0)
 powsinbeta = (float)pow(sinbeta,s2);
 else
 powsinbeta = (float) - pow(- sinbeta,s2);

 return(R*powcosalfa*powsinbeta);
}

/********************** RUTINA DE DIBUJO *********************************/

void igCreateQuadricObject (int pu, int pv, float uMax, float vMax, float R, float s1, float s2)
{
 /* pu es el numero de divisiones en u */
 /* pv es el numero de divisiones en v*/
 float u, v;
 float iniu,iniv;
 float inc_u; //incremento de u
 float inc_v; //incremento de v
 float x, y, z; /*almanezaran las coordenadas en el espacio tridimensional*/
 int   i,j;/*contadores para los bucles for*/
 v= uMax;
 u =vMax;
 iniu=u;
 iniv=v;
 /*El maximo valor de u y v es 1 y el minimo es 0 por lo tanto debemos de distribuir
 las partes exigidas en la distancia establecida entre el valor de inicialización y
 el maximo valor*/
 inc_u= (1.0f-u)/pu;
 inc_v= (1.0f-v)/pv;

 //Dibujamos los paralelos de la esfera
 //tantas circunfencias como partes de v
 for (j=0;j&lt;pv;j++)
 {
 glBegin (GL_LINE_LOOP);//Indicamos a openGL el modo de dibujado
 //indicamos los puntos (partes de u) que formaran la circunferencia
 for (i= 0; i&lt;= pu; i++)
 {
 x= xSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada x del punto
 y= ySuperQuadric (u, v, R, s1, s2);//indicamos la coordenada y del punto
 z= zSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada z del punto
 glVertex3f (x, y, z); //pintamos el punto en el espacio tridimensional
 u= u+ inc_u;//avanzamos hasta el siguiente putno
 //printf(&quot;valor de v=%f valor de u=%f\n&quot;,v,u);
 if (u&gt;1){u=iniu;}
 }
 glEnd();//indicamos a openGL que hemos acabado de indicar los puntos de la circunferencia

 v+=inc_v;//avanzamos a la siguiente circunferencia paralela
 }

 u=iniu;
 v=iniv;
 //Dibujamos os meridianos de la esfera
 //tantos meridianos como partes de v
 for (j=0;j&lt;pu;j++)
 {
 glBegin(GL_LINE_STRIP);//Indicamos a OpenGL el modo de dibujado
 //Indicamos los puntos (partes de v) que formaran el meridiano
 v=iniv;
 for(i=0;i&lt;=pv;i++)
 {
 x= xSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada x del punto
 y= ySuperQuadric (u, v, R, s1, s2);//indicamos la coordenada y del punto
 z= zSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada z del punto
 glVertex3f (x, y, z); //pintamos el punto en el espacio tridimensional
 v+=inc_v;//avanzamos hasta el siguiente punto

 //printf(&quot;valor de v=%f valor de u=%f\n&quot;,v,u);
 }
 //printf(&quot;Meridiano dibujado\n\n&quot;);
 glEnd();//Indicamos a openGL que ya hemos señalado los puntos del meridiano
 u+=inc_u;//avanzamos al siguiente meridiano

 }
}

void igWireSphere (int pu, int pv)
{
 /* s1 y s2 a 1 */
 igCreateQuadricObject(pu,pv,0,0,1.0, 1, 1);

}

void igWireRulo (int pu, int pv)
{
 /* s1= 0.5, s2= 1 */
 igCreateQuadricObject(pu,pv,0,0,1.0, 0.5, 1);

}

void igWireDado (int pu, int pv)
{
 /* s1= 0.5, s2 =0.5 */
 igCreateQuadricObject(pu,pv,0,0,1.0, 0.5, 0.5);

}
void igWireSemiSphere (int pu, int pv)
{

 /* s1 y s2 a 1, uMax= 1, vMax= 0.5 */
 igCreateQuadricObject(pu,pv,0,0.5,1.0, 1, 1);

}

void igWireCubo (void)
{
 //Centramos en el origen de las coordenadas
 //El radio es 1
 glBegin (GL_LINE_LOOP);
 //aristas traseras
 glVertex3f(-0.5,-0.5,-0.5);
 glVertex3f(0.5, -0.5, -0.5);
 glVertex3f(0.5,0.5,-0.5);
 glVertex3f(-0.5,0.5,-0.5);
 glVertex3f(-0.5,-0.5,-0.5);
 //parte delantera
 glVertex3f(-0.5,-0.5,0.5);
 glVertex3f(-0.5,0.5,0.5);
 glVertex3f(0.5,0.5,0.5);
 glVertex3f(0.5,-0.5,0.5);
 glVertex3f(-0.5,-0.5,0.5);
 //lado izquierdo
 glVertex3f(-0.5,-0.5,-0.5);
 glVertex3f(-0.5,-0.5,0.5);
 glVertex3f(-0.5,0.5,0.5);
 glVertex3f(-0.5,0.5,-0.5);
 glVertex3f(0.5,0.5,-0.5);
 glVertex3f(0.5,0.5,0.5);
 glVertex3f(0.5,-0.5,0.5);
 glVertex3f(0.5,-0.5,-0.5);
 glEnd ();
}

void igWireCone (int pu, int pv)
{
/* s1= 2.0, s2= 1.0, uMax= 1.0, vMax= 0.5 */
 igCreateQuadricObject(pu, pv, 0.5, 0, 1, 2.0, 1.0);
}

void CreaAbetoPush(void)
 {
 //abetoPush= glGenLists(1);
 if (abetoPush != 0)
 {
 glNewList( abetoPush, GL_COMPILE);
 glColor3f(1,0,0);

 glPushMatrix();
 glRotated(180,0,0,1);
 glScalef(0.75, 1, 0.75);
 igWireCone(20, 20);
 glPopMatrix();

 glPushMatrix();
 glTranslatef(0,0.25, 0);
 glRotated(180,0,0,1);
 glScalef(0.75, 1, 0.75);
 glScalef(0.75, 1, 0.75);
 igWireCone(20, 20);
 glPopMatrix();

 glPushMatrix();
 glTranslatef(0, 0.5, 0);
 glRotated(180,0,0,1);
 glScalef(0.75, 1, 0.75);
 glScalef(0.75, 1, 0.75);
 glScalef(0.75, 1, 0.75);
 igWireCone(20, 20);
 glPopMatrix();

 glPushMatrix();
 glRotated(180,0,0,1);
 glScalef(0.75, 1, 0.75);
 glScalef(0.75, 1, 0.75);
 glScalef(0.75, 1, 0.75);
 glScalef(0.5, 1, 0.5);
 igWireRulo(15, 5);
 glPopMatrix();

 glEndList();
 }
 else
 {
 printf(&quot;Error al crear abetoPush\n&quot;);
 }

 }

void CreaAbeto (void)
{
 //abeto = glGenLists (1);
 if (abeto != 0) /* Cero no es un identificador valido para una display list */
 {
 glNewList (abeto, GL_COMPILE);
 /* Código para dibujar el abeto */
 /*Sx=0.75 Sy=1.0 Sz=0.75*/
 glColor3f(0,1,0);
 glRotated(180,0,0,1);
 glScalef(0.75,1,0.75);
 igWireCone(20, 20);
 glScalef(0.75,1,0.75);
 glTranslatef(0,-0.25,0);
 igWireCone(20, 20);
 glScalef(0.75,1,0.75);
 glTranslatef(0,-0.25,0);
 igWireCone(20, 20);
 glTranslatef(0, 0.5, 0);
 glScalef(0.5, 1, 0.5);
 igWireRulo(15, 5);
 glEndList ();
 }
}
void CreaEscalera(void)
 {
 int x;
 glNewList(escalera, GL_COMPILE);
 printf(&quot;mierda\n&quot;);
 //# Dibuja una caja a modo de eje de la escalera de altura=2.0 y lado= 0.2
 escalon();
 for(x=0;x&lt;100;x++)
 {
 glPushMatrix();
 glRotated(90,1,0,0);
 //Sx=0.5 Sy= 0.05 Sz=0.1
 glScalef(0.5, 0.5, 0.1);

 glTranslatef(0,  0,-x*(0.2));
 glRotated((360/50)*x,0,0,1);
 escalon();
 glPopMatrix();
 }
 glEndList();

 }

void escalon(void)
 {
 glBegin (GL_LINE_LOOP);
 //base
 glVertex3f(-0.1,0,-0.1);
 glVertex3f(0.1,0,-0.1);
 glVertex3f(0.1,0,0.1);
 glVertex3f(-0.1,0,0.1);
 glVertex3f(-0.1,0,-0.1);
 //subimos
 glVertex3f(-0.1,2,-0.1);
 glVertex3f(0.1,2,-0.1);
 //bajamos y subimos
 glVertex3f(0.1,0,-0.1);
 glVertex3f(0.1,2,-0.1);
 glVertex3f(0.1,2,0.1);
 //bajamos y subimos
 glVertex3f(0.1,0,0.1);
 glVertex3f(0.1,2,0.1);
 glVertex3f(-0.1,2,0.1);
 //bajamos y subimos
 glVertex3f(-0.1,0,0.1);
 glVertex3f(-0.1,2,0.1);
 glVertex3f(-0.1,2,-0.1);
 glEnd();
 }

void CreaPatio(void)
 {
 int x;

 glNewList( patio , GL_COMPILE);
 for(x=0;x&lt;12;x++)
 {
 glPushMatrix();
 glScalef(0.2, 0.2, 0.2);
 glRotated(30*x, 0, 1, 0);
 glTranslatef(0, 0, -4);
 arco();
 glPopMatrix();
 }
 glEndList();
 }

void arco(void)
 {
 glPushMatrix();
 //glColor3f(1, 0, 0);//rojo
 glTranslatef(-0.75, 0, 0);
 columna();
 glPopMatrix();
 glPushMatrix();
 //glColor3f(0, 1, 0);//verde
 glTranslatef(0.75, 0, 0);
 columna();
 glPopMatrix();
 glPushMatrix();
 //glColor3f(0, 0, 1);//azul
 glRotated(270, 0, 0, 1);
 glTranslatef(-1.75, -1, 0);
 columna();
 glPopMatrix();
 }

void columna(void)
 {
 glBegin (GL_LINE_LOOP);
 //base
 glVertex3f(-0.25,0,-0.25);
 glVertex3f(0.25,0,-0.25);
 glVertex3f(0.25,0,0.25);
 glVertex3f(-0.25,0,0.25);
 glVertex3f(-0.25,0,-0.25);
 //subimos
 glVertex3f(-0.25,2,-0.25);
 glVertex3f(0.25,2,-0.25);
 //bajamos y subimos
 glVertex3f(0.25,0,-0.25);
 glVertex3f(0.25,2,-0.25);
 glVertex3f(0.25,2,0.25);
 //bajamos y subimos
 glVertex3f(0.25,0,0.25);
 glVertex3f(0.25,2,0.25);
 glVertex3f(-0.25,2,0.25);
 //bajamos y subimos
 glVertex3f(-0.25,0,0.25);
 glVertex3f(-0.25,2,0.25);
 glVertex3f(-0.25,2,-0.25);

 glEnd();
 }

Informática Gráfica Práctica 3. Modelado geométrico.

1. Vas a construir, paso a paso, una rutina que dibuje una supercuádrica. Esta función calcula un conjunto de puntos 3d de la superficie y al mismo tiempo los dibuja unidos mediante líneas utilizando la primitiva de OpenGL GL_LINE_LOOP. Para empezar, copia y pega la siguiente rutina en tu fichero glig.c. Observa el código y mira lo que ocurre al fijar el valor de v a 0.5 y hacer variar la u entre 0 y 1.

void igCreateQuadricObject (float R, float s1, float s2)

{
float u, v, inc_u;
float x, y, z;
int   i, pu = 10;  /* pu es el numero de divisiones en u */

v= 0.5f;
u =0.0f;
inc_u= 1.0f/pu;

glBegin (GL_LINE_LOOP);
for (i= 0; i< 10; i++)

{

x= xSuperQuadric (u, v, R, s1, s2);
y= ySuperQuadric (u, v, R, s1, s2);
z= zSuperQuadric (u, v, R, s1, s2);
glVertex3f (x, y, z);
u= u+ inc_u;
}
glEnd();
}

Llama a esta función con R, s1 y s2 a 1.0 desde la función Dibuja. Acuérdate de declararla en el fichero glig.h y de incluir este en examinar.c.

2. Si ya has entendido el código anterior, modifícalo para que la v también varíe entre 0 y 1 de forma que se dibuje una circunferencia para cada valor diferente de v. Como resultado debes obtener algo similar a la siguiente figura.

3. En el ejercicio anterior has conseguido dibujar los paralelos de la esfera. Ahora vas a dibujar los meridianos. Para ello, además de iterar la u entre 0 y 1 para cada valor de v, vas a iterar la v entre 0 y 1 para cada valor de u. Debes obtener un resultado similar al que se muestra en la siguiente figura

4. Ahora que ya has terminado la rutina vamos a añadir dos nuevos parámetros que permitan al usuario especificar el número de puntos que en u (pu) y en v (pv) se han de calcular (hasta ahora estaban fijados a 10. La declaración de la función es de la siguiente forma:

void igCreateQuadricObject (int pu, int pv, float R, float s1, float s2);

5. Para completar la función, vas a añadir dos nuevos parámetros que permitan acotar el rango de u y v de forma que puedan variar, cada uno de ellos, entre 0 y un valor especificado por el usuario (uMax, vMax). Con ello permitirás que se dibujen primitivas tales como medias esferas. La declaración de la función queda de la siguiente forma:

void igCreateQuadricObject (int pu, int pv, float uMax, float vMax, float R, float s1, float s2);

6. Añade las siguientes funciones a tu biblioteca de forma que cada una de ellas llame a la función igCreateQuadricObject con los parámetros oportunos para que dibuje la primitiva correspondiente en cada caso:

void igWireSphere (int pu, int pv); /* s1 y s2 a 1 */
void igWireRulo (int pu, int pv); /* s1= 0.5, s2= 1 */
void igWireDado (int pu, int pv); /* s1= 0.5, s2 =0.5 */
void igWireSemiSphere (int pu, int pv); /* s1 y s2 a 1, uMax= 1, vMax= 0.5 */

7. Añade a tu biblioteca la primitiva geométrica Cubo mediante la función void igWireCubo (void) . Esta primitiva debe tener de lado 1 y estar centrada en el origen de coordenadas. Haz un esquema en el papel para determinar en primer lugar los valores de las coordenadas de los ocho vértices. Después, crea una vector con las coordenadas de los vértices y, finalmente, escribe el código que dibuje sus aristas.

Las llamadas a función para dibujar las figuras se encuentran en la función IniciaCuadricas

igWireSphere

igWireSemisphere

igWireRulo

igWireDado

examinar.h


/*************************************************************************/
/*                                                                       */
/*   examinar.h                                                          */
/*   Rev. 2.0  01/01/2002   AUTORES: O. Belmonte, M. Chover, J. Ribelles */
/*                                                                       */
/*************************************************************************/

#ifndef EXAMINAR_H
#define EXAMINAR_H

/* Variables Globales del modulo */
int VentanaAncho = 500, VentanaAlto = 500; /* Tamanyo de la ventana */
int VentanaX = 100, VentanaY = 100; /* Posicion de la ventana */
GLdouble  alfa = 0.0, beta = 0.0;
GLuint cuadrica;

/* Abre una ventana OpenGL */
void AbreVentana (int numeroArgumentos, char ** listaArgumentos);

/* Funcion de dibujado */
void Dibuja(void);

/* Establece el area visible */
void TamanyoVentana (int alto, int ancho);

/* Inicia las funciones de Callback */
void IniciaFuncionesCallback (void);

/* Define las acciones tras una pulsacion del teclado */
void Teclado (unsigned char tecla, int x, int y);

/* Define las acciones tras una pulsacion del teclado ampliado */
void TecladoAmpliado (int tecla, int x, int y);
/*Dibuja un Cubo*/
void igWireCubo (void);

void igCreateQuadricObject (int pu, int pv,  float uMax, float vMax,float R, float s1, float s2);
void igWireSphere (int pu, int pv); /* s1 y s2 a 1 */
void igWireRulo (int pu, int pv); /* s1= 0.5, s2= 1 */
void igWireDado (int pu, int pv); /* s1= 0.5, s2 =0.5 */
void igWireSemiSphere (int pu, int pv); /* s1 y s2 a 1, uMax= 1, vMax= 0.5 */

void salir();
#endif

examinar.c


/*************************************************************************/
/*                                                                       */
/*   examinar.c                                                          */
/*   Rev. 2.0  01/01/2002   AUTORES: O. Belmonte, M. Chover, J. Ribelles */
/*                                                                       */
/*************************************************************************/

/***************** INCLUDES DE LAS LIBRERIAS NECESARIAS ******************/
//#include <GL/freeglut.h>
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include "examinar.h"
#include "glig.h"

/******************************************************************************************/
/* Establece el area visible y el tipo de proyeccion                                      */
/* Parametros: int ancho --> Ancho del area visible                                       */
/*             int alto --> Alto del area visible                                         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void TamanyoVentana (GLsizei ancho, GLsizei alto)
{
/* Definicion del viewport */
glViewport(0, 0, ancho, alto);

/* Definicion de la vista */
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-2.0, 2.0, -2.0*(GLfloat)alto/(GLfloat)ancho, 2.0*(GLdouble)alto/(GLfloat)ancho, -2.0, 2.0);
}

/******************************************************************************************/
/* Abre una ventana OpenGL                                                                */
/* Parametros: int numeroArgumentos --> El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --> Vector de cadenas con cada argumento           */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void AbreVentana (int numeroArgumentos, char ** listaArgumentos)
{
glutInit(&numeroArgumentos, listaArgumentos);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (VentanaAncho, VentanaAlto);
glutInitWindowPosition (VentanaX, VentanaY);
glutCreateWindow (listaArgumentos[0]);
glutDisplayFunc (Dibuja);
glutReshapeFunc (TamanyoVentana);
glClearColor (0.0f, 0.0f, 0.0f, 0.0f); /* Establece el color de borrado */
glClear (GL_COLOR_BUFFER_BIT); /* Borra el buffer de color */
glColor3f (1.0f, 1.0f, 1.0f); /* Establece el color de dibujo */
}

/******************************************************************************************/
/* Define las acciones tras una pulsacion del teclado                                     */
/* Parametros: unsigned char key --> Codigo de la tecla pulsada                           */
/*             int x --> Coordenada x del cursor en el momento de pulsar la tecla         */
/*             int y --> Coordenada y del cursor en el momento de pulsar la tecla         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void Teclado (unsigned char tecla, int x, int y)
{
switch (tecla)
{
case 27 : /* Codigo de la tecla de Escape */
exit(0);
break;
}
}

/******************************************************************************************/
/* Define las acciones tras una pulsacion del teclado ampliado                            */
/* Parametros: unsigned char key --> Codigo de la tecla pulsada                           */
/*             int x --> Coordenada x del cursor en el momento de pulsar la tecla         */
/*             int y --> Coordenada y del cursor en el momento de pulsar la tecla         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void TecladoAmpliado (int tecla, int x, int y)
{
switch (tecla)
{
case GLUT_KEY_UP : /* Pulsacion cursor arriba del teclado ampliado */
beta = beta + 15.0;
if (beta > 360.0) beta = beta - 360.0;
break;

case GLUT_KEY_DOWN : /* Pulsacion cursor abajo del teclado ampliado */
beta = beta - 15.0;
if (beta < 0.0) beta = beta + 360.0;
break;

case GLUT_KEY_RIGHT : /* Pulsacion cursor derecha del teclado ampliado */
alfa = alfa + 15.0;
if (alfa > 360.0) alfa = alfa - 360.0;
break;

case GLUT_KEY_LEFT : /* Pulsacion cursor izquierda del teclado ampliado */
alfa = alfa - 15.0;
if (alfa < 0.0) alfa = alfa + 360.0;
break;
}
glutPostRedisplay ();
}

/* Rutina de definiciÛn de eventos */
/******************************************************************************************/
/* Inicia las funciones de callback                                                       */
/* Parametros: Ninguno                                                                    */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void IniciaFuncionesCallback (void)
{
glutKeyboardFunc (Teclado);
glutSpecialFunc (TecladoAmpliado);
}

/******************************************************************************************/
/* Funcion de dibujado                                                                    */
/* Parametros: Ninguno                                                                    */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void Dibuja (void)
{
glClear (GL_COLOR_BUFFER_BIT);

/* Transformacion de la camara */
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotated (beta, 1.0,0.0,0.0);
glRotated (-alfa, 0.0,1.0,0.0);

glCallList (cuadrica);
/* Objetos */
//glutWireTeapot(1.0);
//glutWireIcosahedron();
//glutWireTetrahedron();
//glutWireOctahedron();
//glutWireDodecahedron();
//glutWireTorus(0.2,0.9,18,20);
//glutWireCone(0.5, 2.0, 14, 14);
//glutWireCube(1.0);
//glutWireSphere(1, 20,50);

//igCreateQuadricObject(50,80,0,0,1.0, 1, 1);
//igWireSphere (50, 50);

//igWireRulo (200, 200);
//igWireDado (60, 60);
//igWireSemiSphere (50, 50); // s1 y s2 a 1, uMax= 1, vMax= 0.5 */
//igWireCubo();
glFlush();
}

void igCreateQuadricObject (int pu, int pv, float uMax, float vMax, float R, float s1, float s2)
{
/* pu es el numero de divisiones en u */
/* pv es el numero de divisiones en v*/
float u, v;
float iniu,iniv;
float inc_u; //incremento de u
float inc_v; //incremento de v
float x, y, z; /*almanezaran las coordenadas en el espacio tridimensional*/
int   i,j;/*contadores para los bucles for*/
v= uMax;
u =vMax;
iniu=u;
iniv=v;
/*El maximo valor de u y v es 1 y el minimo es 0 por lo tanto debemos de distribuir
las partes exigidas en la distancia establecida entre el valor de inicialización y
el maximo valor*/
inc_u= (1.0f-u)/pu;
inc_v= (1.0f-v)/pv;

//Dibujamos los paralelos de la esfera
//tantas circunfencias como partes de v
for (j=0;j<pv;j++)
{
glBegin (GL_LINE_LOOP);//Indicamos a openGL el modo de dibujado
//indicamos los puntos (partes de u) que formaran la circunferencia
for (i= 0; i<= pu; i++)
{
x= xSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada x del punto
y= ySuperQuadric (u, v, R, s1, s2);//indicamos la coordenada y del punto
z= zSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada z del punto
glVertex3f (x, y, z); //pintamos el punto en el espacio tridimensional
u= u+ inc_u;//avanzamos hasta el siguiente putno
//printf("valor de v=%f valor de u=%f\n",v,u);
if (u>1){u=iniu;}
}
glEnd();//indicamos a openGL que hemos acabado de indicar los puntos de la circunferencia

v+=inc_v;//avanzamos a la siguiente circunferencia paralela
}

u=iniu;
v=iniv;
//Dibujamos os meridianos de la esfera
//tantos meridianos como partes de v
for (j=0;j<pu;j++)
{
glBegin(GL_LINE_STRIP);//Indicamos a OpenGL el modo de dibujado
//Indicamos los puntos (partes de v) que formaran el meridiano
v=iniv;
for(i=0;i<=pv;i++)
{
x= xSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada x del punto
y= ySuperQuadric (u, v, R, s1, s2);//indicamos la coordenada y del punto
z= zSuperQuadric (u, v, R, s1, s2);//indicamos la coordenada z del punto
glVertex3f (x, y, z); //pintamos el punto en el espacio tridimensional
v+=inc_v;//avanzamos hasta el siguiente punto

//printf("valor de v=%f valor de u=%f\n",v,u);
}
//printf("Meridiano dibujado\n\n");
glEnd();//Indicamos a openGL que ya hemos señalado los puntos del meridiano
u+=inc_u;//avanzamos al siguiente meridiano

}
}

void igWireSphere (int pu, int pv)
{
/* s1 y s2 a 1 */
igCreateQuadricObject(pu,pv,0,0,1.0, 1, 1);

}

void igWireRulo (int pu, int pv)
{
/* s1= 0.5, s2= 1 */
igCreateQuadricObject(pu,pv,0,0,1.0, 0.5, 1);

}

void igWireDado (int pu, int pv)
{
/* s1= 0.5, s2 =0.5 */
igCreateQuadricObject(pu,pv,0,0,1.0, 0.5, 0.5);

}
void igWireSemiSphere (int pu, int pv)
{

/* s1 y s2 a 1, uMax= 1, vMax= 0.5 */
igCreateQuadricObject(pu,pv,0,0.5,1.0, 1, 1);

}

void igWireCubo (void)
{
//Centramos en el origen de las coordenadas
//El radio es 1
glBegin (GL_LINE_LOOP);
//aristas traseras
glVertex3f(-0.5,-0.5,-0.5);
glVertex3f(0.5, -0.5, -0.5);
glVertex3f(0.5,0.5,-0.5);
glVertex3f(-0.5,0.5,-0.5);
glVertex3f(-0.5,-0.5,-0.5);
//parte delantera
glVertex3f(-0.5,-0.5,0.5);
glVertex3f(-0.5,0.5,0.5);
glVertex3f(0.5,0.5,0.5);
glVertex3f(0.5,-0.5,0.5);
glVertex3f(-0.5,-0.5,0.5);
//lado izquierdo
glVertex3f(-0.5,-0.5,-0.5);
glVertex3f(-0.5,-0.5,0.5);
glVertex3f(-0.5,0.5,0.5);
glVertex3f(-0.5,0.5,-0.5);
glVertex3f(0.5,0.5,-0.5);
glVertex3f(0.5,0.5,0.5);
glVertex3f(0.5,-0.5,0.5);
glVertex3f(0.5,-0.5,-0.5);
glEnd ();
}

void IniciaCuadricas (void)

{

cuadrica = glGenLists (1);

if (cuadrica != 0) /* Cero no es un identificador valido para una display list */

{

glNewList (cuadrica, GL_COMPILE);

//igCreateQuadricObject (20,20,0,0,1.0f, 1.0f, 1.0f);

//igWireCubo();

//igWireDado(20,20);

//igWireRulo(10, 20);

igWireSemiSphere(20,20);

glEndList ();

}

}

/******************************************************************************************/
/* Funcion principal                                                                      */
/* Parametros: int numeroArgumentos --> El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --> Vector de cadenas con cada argumento           */
/* Salida: Un entero que se devuelve al sistema al acabar la ejecucion del programa       */
/******************************************************************************************/
int main(int numArgumentos, char ** listaArgumentos)
{
/* CreaciÛn de la ventana de la aplicaciÛn */
AbreVentana (numArgumentos, listaArgumentos);

/* Rutinas para el control de eventos */
IniciaFuncionesCallback ();

IniciaCuadricas();
/* A la espera de eventos.... */
glutMainLoop();

return (0);
}

Informática Gráfica Interactividad

En esta parte de la práctica aprenderás a utilizar las posibilidades que ofrece la biblioteca funciones de utilidades glut de OpenGL para dotar a tu aplicación de interacción con el usuario. Estudia como maneja los eventos producidos por la pulsación de los botones del ratón o de las teclas en el teclado alfanumérico.

La tarea interactiva más simple que implementa la librería glut es permitir que se controle la ejecución de la aplicación mediante un bucle principal de visualización. El formato de la orden es:

void glutMainLoop (void);

La ejecución de esta función espera a que se produzcan eventos. Cada vez que se produce un evento lo atiende y ejecuta la función registrada, encargada de responder al evento (función de callback).

Los posibles eventos que puede responder OpenGL se dividen en tres grupos:

Eventos de ventana.

Se generan al crear la ventana de la aplicación, cambiar su tamaño o su posición en la pantalla. Los eventos de ventana se atienden registrando una función de respuesta con la función:

void glutReshapeFunc (void (*func)(int ancho, int alto));

Eventos de teclado.

Se generan al pulsar alguna tecla. Se atienden definiendo una función de respuesta con la función:

void glutKeyboardFunc (void (*func)(unsigned char key, int x, int y));

Eventos de ratón.

Para registrar la función de respuesta cuando se produce una pulsación de algún botón del ratón se usa:

void glutMouseFunc (void (*func) (int boton, int estado, int x, int y);

Para registrar la función de respuesta cuando el ratón se está moviendo sobre la ventana activa se usa;

void glutMotionFunc (void (*func)(int x, int y));

En esta práctica vamos a trabajar con los eventos de teclado y ratón, dejando los de ventana para prácticas posteriores.

1. Crea un proyecto nuevo y añade los ficheros: raton.c y raton.h. En primer lugar examina el código y pregunta a tu profesor de prácticas cualquier cosa que no entiendas. Compila y ejecuta el código. Comprueba el funcionamiento del programa presionando el botón izquierdo del ratón y las teclas r , g y Esc.

2. Modifica el código para que además atienda a los siguientes eventos de teclado:

Tecla ‘b’ fija el color a azul
Tecla ‘y’ fija el color a amarillo
Tecla ‘R’ fija el color de fondo a rojo
Tecla ‘G’ fija el color de fondo a verde
Tecla ‘B’ fija el color de fondo a azul
Tecla ‘Y’ fija el color de fondo a amarillo

OpenGL trabaja con el espacio de colores llamado RGB (Red Green Blue, o bién rojo verde azul). Así lo especificamos al haber llamado a glutInitDisplayMode(). Cada color está definido por tres valores entre 0 y 1, ambos incluídos. La siguiente tabla contiene las definiciones de los colores mas llamativos:

color     componente(red)     componente(green)     componente(blue)
rojo         1.0             0.0             0.0
verde         0.0             1.0             0.0
azul         0.0             0.0             1.0
blanco         1.0             1.0             1.0
negro         0.0             0.0             0.0
amarillo     1.0             1.0             0.0
magenta     1.0             0.0             1.0
cyan         0.0             1.0             1.0

3. Modifica el código para que al pulsar el botón derecho del ratón se borre la ventana.

4. Modifica de nuevo el código de forma que al pulsar el botón izquierdo del ratón se capture el primer punto de la recta, y al soltarlo se capture el segundo y se dibuje la recta que une ambos puntos.

5. Modifica el código para que antes de soltar el botón izquierdo siempre sea visible la recta que se dibujaría.

6. Modifica el código de forma que los dos puntos indicados por el usuario sean la diagonal de un rectángulo y lo visualice.

7. Añade un evento de teclado que te permita seleccionar entre dibujar líneas y rectángulos.

libreria .h

#ifndef OCUADRADO_H
#define OCUADRADO_H

/* Variables Globales del modulo */
int VentanaAncho = 500, VentanaAlto = 500; /* Tamanyo de la ventana */
int VentanaX = 100, VentanaY = 100; /* Posicion de la ventana */
int Pulsaciones; /* Numero de pulsaciones del boton izquierdo del raton */
int InicioX, InicioY; /* Coordenadas del punto inicial */
int FinX, FinY; /* Coordenadas del punto final */
float cpR,cpG,cpB;/*Color Pintado red color Pintado Green and Color Pintado Blue*/
float cfR,cfG,cfB;/*Colores de fondo*/
int modoLinea;//Booleando en true dibuja lineas en falso dibuja rectangulos o cuadrados

/* Abre una ventana OpenGL */
void AbreVentana (int numeroArgumentos, char ** listaArgumentos);

/* Funcion de dibujado */
void Dibuja(void);

/* Establece el area visible */
void TamanyoVentana (int alto, int ancho);

/* Inicia las funciones de Callback */
void IniciaFuncionesCallback (void);

/* Define las acciones tras una pulsacion del teclado */
void TecladoCallback (unsigned char tecla, int x, int y);

/* Funcion de callback de las acciones del raton */
void RatonCallback (int boton, int estado, int x, int y);

#endif

el archivo c

#include <GL/freeglut.h>
#include <stdio.h>
#include "main.h"

#ifndef FALSE
#define FALSE (0)
#define TRUE (!(FALSE))
#endif

/******************************************************************************************/
/* Funcion de dibujado                                                                    */
/* Parametros: Ninguno                                                                    */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void Dibuja(void)
{
 if (!modoLinea)
 {
 int ymenor,ymayor,xmenor,xmayor;

 if (InicioX<FinX)
 {
 xmenor=InicioX;
 xmayor=FinX;
 }
 else
 {
 xmenor=FinX;
 xmayor=InicioX;
 }
 if (VentanaAlto-InicioY<VentanaAlto-FinY)
 {
 ymenor=VentanaAlto-InicioY;
 ymayor=VentanaAlto-FinY;
 }
 else
 {
 ymenor=VentanaAlto-FinY;
 ymayor=VentanaAlto-InicioY;
 }
 glBegin(GL_POLYGON);
 glVertex2i(xmenor,ymenor);
 glVertex2i(xmayor,ymenor);
 glVertex2i(xmayor, ymayor);
 glVertex2i(xmenor, ymayor);
 }
 else
 {
 /* Dibuja un segmento de linea entre el punto incial y el final */
 glBegin (GL_LINES);
 glVertex2i (InicioX, VentanaAlto-InicioY);
 glVertex2i (FinX, VentanaAlto-FinY);
 }
glEnd ();
/* Se asegura de que se ejecutan todas las ordenes */
glFlush ();
}

/******************************************************************************************/
/* Establece el area visible y el tipo de proyeccion                                      */
/* Parametros: int ancho --> Ancho del area visible                                       */
/*             int alto --> Alto del area visible                                         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void TamanyoVentana (int ancho, int alto)
{
 glMatrixMode(GL_PROJECTION); /* Activamos la matriz de proyeccion */
 glLoadIdentity(); /* la iniciamos con la matriz identidad */
 glOrtho(0.0, ancho, 0.0, alto, -1.0, 1.0); /* establecemos los parametros de la proyeccion */
 glViewport (0, 0, ancho, alto); /* establecemos los parametros del area de dibujo */
 VentanaAncho = ancho; /* guardamos el ancho y alto de la ventana */
 VentanaAlto = alto;
 glClear (GL_COLOR_BUFFER_BIT); /* borramos la ventana */
 InicioX = InicioY = FinX = FinY = Pulsaciones = 0; /* Inica las variables */
}

/******************************************************************************************/
/* Abre una ventana OpenGL                                                                */
/* Parametros: int numeroArgumentos --> El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --> Vector de cadenas con cada argumento           */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void AbreVentana (int numeroArgumentos, char ** listaArgumentos)
{
 modoLinea=TRUE;
 glutInit(&numeroArgumentos, listaArgumentos);
 glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
 glutInitWindowSize (VentanaAncho, VentanaAlto);
 glutInitWindowPosition (VentanaX, VentanaY);
 glutCreateWindow (listaArgumentos[0]);
 glutDisplayFunc (Dibuja);
 glutReshapeFunc (TamanyoVentana);
 glClearColor (0.0f, 0.0f, 0.0f, 0.0f); /* Establece el color de borrado */
 glClear (GL_COLOR_BUFFER_BIT); /* Borra el buffer de color */
 glColor3f (1.0f, 1.0f, 1.0f); /* Establece el color de dibujo */
}

void EstableceColorFondo(float r, float g, float b)
{
 cfR=r;
 cfG=g;
 cfB=b;
 glClearColor(cfR,cfG,cfB,0.0f); /* Establece el color de borrado */
 glClear (GL_COLOR_BUFFER_BIT); /* Borra el buffer de color */
 glFlush ();

}

void EstableceColorPintado(float r, float g, float b)
{
 cpR=r;
 cpG=g;
 cpB=b;
 glColor3f(cpR, cpG, cpB);
}

/******************************************************************************************/
/* Define las acciones tras una pulsacion del teclado                                     */
/* Parametros: unsigned char key --> Codigo de la tecla pulsada                           */
/*             int x --> Coordenada x del cursor en el momento de pulsar la tecla         */
/*             int y --> Coordenada y del cursor en el momento de pulsar la tecla         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void TecladoCallback (unsigned char tecla, int x, int y)
{
 switch (tecla)
 {
 case 27 : /* Codigo de la tecla de Escape */
 exit(0);
 break;

 case 'c':
 if (modoLinea==TRUE)
 {modoLinea=FALSE;
 printf("Cambiando a nodo cuadrados\n");
 }
 else
 {modoLinea=TRUE;
 printf("Cambiando a modo lineas\n");
 }
 case 'r' :
 EstableceColorPintado(1.0f, 0.0f, 0.0f);
 break;

 case 'g' :
 EstableceColorPintado(0.0f, 1.0f, 0.0f);
 break;

 case 'b':
 EstableceColorPintado(0, 0, 1);
 break;

 case 'y':
 EstableceColorPintado(1,1,0);
 break;

 case 'R':
 EstableceColorFondo(1.0f, 0.0f, 0.0f);
 break;

 case 'G':
 EstableceColorFondo(0.0f, 1.0f, 0.0f);
 break;

 case 'B':
 EstableceColorFondo(0.0f, 0.0f, 1.0f);
 break;

 case 'Y':
 EstableceColorFondo(1.0f, 1.0f, 0.0f);
 break;
 }
}

/******************************************************************************************/
/* Funcion de callback de las acciones del raton                                          */
/* Parametros: int boton --> Codigo del boton que se ha pulsado                           */
/*             int estado --> Estado del boton                                            */
/*             int x --> Coordenada x del cursor en el momento de pulsar la tecla         */
/*             int y --> Coordenada y del cursor en el momento de pulsar la tecla         */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void RatonCallback (int boton, int estado, int x, int y)
{
 printf("boton %d estado %d coordenadas: %d,%d\n",boton,estado,x,y);
 if (boton == GLUT_LEFT_BUTTON)
 {

 if (estado == GLUT_DOWN) /* Si el numero de pulsaciones es par, el punto es el inicial */
 {                         /* del segmento */
 InicioX = x;
 InicioY = y;
 printf("esperando levatamiento\n");
 }
 if (estado == GLUT_UP)
 {
 printf("raton levantado\n");
 FinX = x;
 FinY = y;
 glutPostRedisplay ();
 }
 Pulsaciones ++;
 }
 if (boton == GLUT_RIGHT_BUTTON && estado== GLUT_DOWN)
 {
 glClear (GL_COLOR_BUFFER_BIT); /* Borra el buffer de color */
 glutPostRedisplay ();
 }
}

void ratonMoviendose (int x, int y)
 {
 printf("Raton Moviendose: %d,%d \n",x,y);
 //borramos linea anterior
 //guardamos colores de pintado actial
 float cplr,cplg,cplb;
 cplr=cpR;
 cplg=cpG;
 cplb=cpB;
 //cambiamos el color de pintado a negro
 EstableceColorPintado(cfR, cfG, cfB);
 //pintamos una linea del color de fondo en las coordenadas anteriores
 Dibuja();
 //volvemos al aterior color de pintado
 EstableceColorPintado(cplr, cplg, cplb);
 //cambiamos las coordenadas de fin
 FinX = x;
 FinY = y;
 //Dibujamos
 Dibuja();

 }

/******************************************************************************************/
/* Inicia las funciones de callback                                                       */
/* Parametros: Ninguno                                                                    */
/* Salida: Ninguna                                                                        */
/******************************************************************************************/
void IniciaFuncionesCallback (void)
{
 glutKeyboardFunc (TecladoCallback);
 glutMouseFunc (RatonCallback);
 glutMotionFunc(ratonMoviendose);
}

/******************************************************************************************/
/* Funcion principal                                                                      */
/* Parametros: int numeroArgumentos --> El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --> Vector de cadenas con cada argumento           */
/* Salida: Un entero que se devuelve al sistema al acabar la ejecucion del programa       */
/******************************************************************************************/
int main(int numArgumentos, char ** listaArgumentos)
{
 /* Crea la ventana de la aplicaci¢n */
 printf("inicializando referencia\n");
 AbreVentana (numArgumentos, listaArgumentos);
 IniciaFuncionesCallback ();

 /* Establece el bucle principal de control de OpenGL */
 glutMainLoop();

 return (0);
}

Practica 1 Informática Gráfica ultimo ejercicio

El codigo aqui:

/*
* File:   main.c
* Author: luzem
*
* Created on 17 de marzo de 2010, 1:08
*/

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &quot;GL/freeglut.h&quot; //Alternativa a Glut.h
/******************************************************************/
/* Funcion de dibujado                                            */
/* Parametros: Ninguno                                            */
/* Salida: Ninguna                                                */
/******************************************************************/
void Dibuja(void) {
float altura = 1;
float base = -0.5f;
/* Establece el color de borrado */
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

/* Borra el buffer de color */
glClear(GL_COLOR_BUFFER_BIT);

/* Establece el color de dibujo */
glColor3f(1.0f, 1.0f, 1.0f);

/* Crea un poligono 2D (cuadrado) */
glBegin(GL_POLYGON);
glVertex2f(-0.5f, -0.5f);
glVertex2f(-0.5f, 0.5f);
glVertex2f(0.5f, 0.5f);
glVertex2f(0.5f, -0.5f);
glEnd();
int x;
for (x = 0; x &lt; 5; x++) {
if (x % 2 == 0) {
//cuadrado par pintamos de negro
glColor3f(0, 0, 1);
} else {
//cuadrado impar pintamos de verde
glColor3f(0, 1, 0);
}
glBegin(GL_POLYGON);
glVertex2f(base, base);
glVertex2f(base, base + altura);
glVertex2f(base + altura, base + altura);
glVertex2f(base + altura, base);
glEnd();
altura = altura - 0.2;
base = base - 0.02;
}

/* Se asegura de que se ejecutan todas las ordenes */
glFlush();
}

/******************************************************************************************/
/* Establece el area visible                                                              */
/* Parametros: int ancho --&gt; Ancho del area visible                                       */
/*             int alto --&gt; Alto del area visible                                         */
/* Salida: Ninguna                                                                        */

/******************************************************************************************/
void TamanyoVentana(int ancho, int alto) {
glViewport(0, 0, ancho, alto);
}

/******************************************************************************************/
/* Inicia las propiedades de la vista                                                     */
/* Parametros: Ninguno                                                                    */
/* Salida: Ninguna                                                                        */

/******************************************************************************************/
void IniciaVista(void) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
}

/******************************************************************************************/
/* Abre una ventana OpenGL                                                                */
/* Parametros: int numeroArgumentos --&gt; El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --&gt; Vector de cadenas con cada argumento           */
/* Salida: Ninguna                                                                        */

/******************************************************************************************/
void AbreVentana(int numeroArgumentos, char ** listaArgumentos) {
glutInit(&amp;numeroArgumentos, listaArgumentos);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(listaArgumentos[0]);
glutDisplayFunc(Dibuja);
glutReshapeFunc(TamanyoVentana);
IniciaVista();
}

/******************************************************************************************/
/* Funcion principal                                                                      */
/* Parametros: int numeroArgumentos --&gt; El numero de argumentos en la llamada al programa */
/*             char ** listaArgumentos --&gt; Vector de cadenas con cada argumento           */
/* Salida: Un entero que se devuelve al sistema al acabar la ejecucion del programa       */

/******************************************************************************************/
int main(int numArgumentos, char ** listaArgumentos) {
/* Crea la ventana de la aplicaci¢n */
AbreVentana(numArgumentos, listaArgumentos);

/* Establece el bucle principal de control de OpenGL */
glutMainLoop();

return (0);
}

El resto de la película en libreta de notas enjoy.

Una visión general de RMI

“Esto es una traduccion on the fly de http://java.sun.com/docs/books/tutorial/rmi/overview.html”

RMI (Java Remote Method Invocatión) es la tecnología que nos ofrece Java para ejecutar metodos en una maquina virtual remota.

Supongamos que tenemos nuestro programa ejecutándose en nuestro PC Local (Un pentium II 350) y necesitamos realizar llamar a un método que ejecuta un abultado numero de threads para calcular algo y en la oficina es todo maquinaria antigua excepto un UltraSPARC T1  que nos reduce el tiempo de espera en unos cuantos minutos.

En un escenario como el descrito anteriormente RMI se perfila como una alternativa a tener en cuenta.

Las aplicaciones que utilicen objetos remotos necesitan realizar las siguientes acciones:

  • Localizar Objetos Remotos Las aplicaciones pueden utilizar diversos mecanismos para obtener referencias de objetos remotos. Por ejemplo: Una aplicación puede registrar sus objetos remotos con las características del registro de RMI o de forma alternativa una aplicacion puede trabajar con referencias de objetos distribuidos en sus metodos locales.
  • Comunicarse con Objetos Remotos Los detalles de la comunicación entre objetos remotos son gestionadas por RMI, para el programador la comunicación remota actuá como las llamadas clásicas a métodos.
  • Cargar las definiciones de las clases para los objetos que recibe RMI permite que los objetos sean devueltos, por eso incluye mecanismos para cargar definiciones de objetos y transmitir los datos de los mismos.

La siguiente ilustración describe una aplicación distribuida que usa el registro RMI para obtener una referencia a un objeto remoto. El servidor llama al registro para asociar un nombre con un objeto remoto. El cliente busca el objeto remoto en el registro del servidor y despues llama a un metodo del objeto. La ilustración también muestra como RMI utiliza un servidor web existente para obtener las definiciones de las clases. en la comunicación cliente-servidor y viceversa cuando es necesario

esquema RMI

Ventajas de la carga dinámica de código

Una de las características centrales y únicas de RMI es la capacidad de descargar la definición de un objeto si la clase no esta definida en la maquina virtual del receptor. Todo los tipos y comportamientos de un objeto, anteriormente disponibles en una única maquina virtual, pueden ser transmitidos a otra maquina virtual. RMI transporta objetos con sus clases, el comportamiento de sus objetos no cambia cuando es enviada a otra maquina virtual, de esta manera amplia el comportamiento de la aplicación.

Interfaces remotas, objetos y metodos

Como cualquier otra aplicacion en Java una aplicacion distribuida esta compuesta de interfaces y clases. Una interfaz declara metodos, las clases implementan los metodos declarados por la interfaz y puede contener metodos adicionales. En una aplicacion distribuida algunas implementaciones pueden residir en algunas maquinas virtuales pero no en otras. Objetos con metodos que pueden ser invocados entre maquinas virtuales se llaman objetos remotos.

Un objeto se tranforma en remoto implementando la interfaz remote, que tiene las siguientes caracteristicas:

  • Una interfaz remota extiende la interz java.rmi.Remote.
  • Cada método de la interfaz declara java.rmi.RemoteException en su clausulas throws, en adicción a cualquier excepción especifica de la aplicación.

RMI trata un objeto remoto de una forma diferente a un objeto no remoto cuando el objeto es pasado entre maquinas virtuales. mas que hacer una copia de la implementacion del objeto en la maquina virtual receptora, RMI pasa un stub remoto para un objeto remoto. El stub actua como la representacion local, o proxe, para el objeto remoto y para el cliente como una referencia remota. El cliente invoca al metodo desde el stub local el cual es el reponsable de transportar la invocarcion al metodo en el objeto remoto.

Un stub para un objeto remoto implementa el mismo conjuto de interfaces remotas que el objeto remoto. Esto permite que el stub pueda ser modelado (casting) a cualquiera de las interfaces que el objeto remoto implementas. De todas formas, solo los metods definidos en la interfaz remota estan disponibles para ser invocados el la maquina virtual receptora.

Creando Aplicaciones distrribuidas usando RMI

Utilizar RMI para desarrolar una aplicacion distribuida nos obliga a incluir estos pasos generales

  • Diseñar e implementar los componentes de tu aplicación distribuida
  • Compilar los fuentes
  • Hacer las clases accesibles desde la red
  • iniciar la aplicación

Diseñar e implementar los componentes de tu aplicacion distribuida

Primeramente determina la arquitectura de tu aplicación, incluyendo que componentes son objetos locales y que componentes son acesibles de forma remota. Este paso incluye:

  • Definir las interfaces remotas. Una interfaz remota especifica que métodos puede ser invocados por el cliente. Los programas clientes usan esas interfaces remotas y no la implementación de esas interfaces. El diseño de las interfaces incluye la definicion de los tipos de objetos que seran usados como parametros y valores de retorno para esos metodos. Si alguna de esas intarfaces o clases aun no existe tu deberas definirlas.
  • Implementar los objetos remotos. Los bjetos remotos deben implementar una o mas interfaces romatas. La clase del objeto remoto debe incluir las implementaciones de las otras interfaces y metodos que esten disponibles solo de forma local. Si alguna clase local es usada para parametros o valores de retorno estas deben ser implementadas tambien.
  • Implementar los clientes. Los clientes que usan los objetos remotos pueden ser implimentadas en cualquier momentos despues de que las interfaces remotas esten definidas, incluso despues que los objetos remotos hayan sido desarrollados.

Compilar los Fuentes

Como en cualquier programa en Java, tu debes usar el compilador javac para compilar los fuentes, el codigo fuente contiene las declaraciones de las interfaces remotas, sus implementaciones, cualquier otra clase del servidor y los clases del cliente.

nota: Las versiones ateriores a la Hava Standard Edition 5.0, como paso adicional requieren la creacion de los stub usando rmic

Haciendo las Clases accesibles por la Red

En este paso tu haras que ciertas definiciones de clases sean accesibles en la red, como la definicion de interfaces remotas y sus tipos asocidaos, y la definicion para las clases que necesitan ser descargadas para los clientes o servidores. Las difiniciones de clases generalmente se hacen accesibles a traves de un servidor web.

Construyendo un Motor de computo generico

Nos centraremos en una simple, pero poderosa, aplicación distribuida llamada motor de computo. El motor decomputo es un objeto remoto en el servidor que toma tareas de los clientes, ejecuta las tareas y retorna los resultados. Las tareas estan corriendo en la misma maquina que el servidar. Este tipo de aplicaciones distribuidas puede activar un numero de maquinas cliente para hacer uso de una maquina particularmente potente o con hardware especializado.

Los aspectos noveles del motor de computo son que las tareas que ejecuta no necesitan ser definidas cuando el motor de computo esta escrito o iniciado. Nuevos tipos de tareas pueden ser creados en cualquier momento y después enviadas al motor de computo. El único requerimiento de las tareas es que sus clases implemente una interfaz en particular. El código necesario para cumplir la tarea puede ser descargado por el sistema RMI al motor de computo. Entonces, el motor de computo ejecuta la tarea usando los recursos de la maquina donde ser esta ejecutado dicho motor.

La capacidad para realizar tareas arbitrarias esta disponible por la naturaleza dinámica de la plataforma java, que es extendida a traver de la red gracias a RMI. RMI caga de forma dinámica el código de la tarea en el motor de computo de la maquina virtual de java y ejecuta la tarea sin conocimiento previo de la implementacion de la tarea. Como las aplicaciones  con la capacidad de descargar el codigo de forma dinamica, tambien llamadas aplicaciones basadas en comportamientos, estas aplicaciones requeres una infraestructura de agentes activos. Com RMI estas aplicaciones son parte del mecanismo basica para computacion distribuida de la plataforma java.

Escribiendo un servidor RMI

El servidor del motor de computo acceta tareas de los clientes, ejecuta la tarea y devuelve los resultados, el codigo del servidor consuste en una interfaz y una clases. La interfaz define los metodos que pueden ser invocados por el clientes. Esencialmente lainterfaz define la vista de los objetos remotos para los clientes, la clases nos provee de las implementaciones.

Diseñando Una Interfaz remota

El corazon del motor de computacion es un protocolo que permite que las tareas sean enviadas al mismo, el motor de computo ejecuta esas tareas y el resultado de la ejecución es enviado al cliente. Este protocolo esta introducido en las interfaces que son soportadas por el motor de computo.

Comunicación RMI

Cada interfaz contiene un único método. La interfaz remota del motor de computo, Compute, permite a las tareas ser enviadas al motor. La interfaz cliente, Task, define como el motor de computo ejecuta una tarea enviada.

La interfaz compute.Compute define la parte accesible de forma remota, el motor de computo en si mismo, Aqui pongo el codigo de la interfaz Compute:

package compute;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
<T> T executeTask(Task<T> t) throws RemoteException;
}

Al extender la interfaz java.rmi.Remote, la interfaz compute se identifica como una interfaz cuyos métodos pueden ser invocados desde otra maquina virtual. Cualquier objeto que implementa esta interfaz puede ser un objeto remoto.

Como miembro de una interfaz remota, el método executeTask es un método remoto. De todas formas este método debe ser definido para ser capar de ignorar una java.rmi.RemoteException. Esta excepción es ignorada por el sistema RMI en la invocación de métodos remotos para indicar fallos de comunicación o errores del protocola. Una RemoteExcepcion es una excepción comprobada, pero cualquier código que invoque a un método remoto necesita manejar esta excepción con un catch o con una cláusula throws.

La segunda interfaz necesaria para el motor de computo es la interfaz Task, que es el tipo de parametro del metodo executeTask en la interfaz compute. Aqui teneis es codigo de la interfaz Task

package compute;

public interface Task<T> {
T execute();
}

La interfaz task define un único método, execute, que no tiene parámetros ni ignora ninguna excepción. Porque la interfaz no extiende a Remote y el método de esta interfaz no necesita ignoros la excepción java.rmi.RemoteException en su cláusula throws.

La interfaz Task tiene un tipo de parámetro T, que representa el tipo de resultado de las tareas a computar. Esta interfaz ejecuta métodos que devuelven el resultado del computo.

RMI usa los mecanismos de serializacion de objetos para transportar los objetos por valor entre maquinas virtuales, Para que un objeto pueda ser serializables, su definición debe implementar la interfaz java.io.Serializable. Por lo tanto las clases que implementen la inteaz Task tambien deben implementar la interfaz Serializable.

Los diferentes tipos de tareas que pueden ser ejecutadas por el Objeto Compute son implemntaciones del tipo Task. Las clases que son implementads por esta interfaz pueden contener cualquier informacion necesitada para la ejecucion de la tarea y cualquier otro metod necesario para la ejecución.

Esta es la forma por la cual RMI hace que este simple motor de computo posible. RMI asume que los objetos Task estan escritos en Java, las implementaciones de los objetos Task que eran desconocidos para el motor de computo son obtenidas por RMI baja demanda, esta capacidad permite a los clientes del motor de computo definir nuevos tipor de tareas para ejecutar en el servidor sin la necesidad de especificar nada en el codigo de la parte del servidor.

El motor de computo implementado por la clase ComputeEngine iplementa la interfaz Compute, permitiendo que distintas tareas sean enviadas a el cn llamadas al metodo executeTask. estas tareas se ejecutan usado de implementacion de Task del metodo execute y los resultados son enviados al cliente remoto.

Implementando una interfaz Remota

Una clase que implementa una intergaz emoto necesida hacer lo siguiente:

  • Declarar las interfaces remotas que implementara
  • Definir los constructores para cada objeto remoto
  • Implementar cada metodo remoto de las interfaces remotas

Un servidor RMI necesita crear los objetos remotos iniciales y exportarlos al entrono de ejecución RMI, lo que les permite al servidor recibir invocaciones remotas. Este paradigma de funcionamiento puede ser encapsulado en un metodo de la implementación del objeto remoto o ser incluida en otra clase. El paradigma de funcionamiento debe realizar la siguientes acciones:

  • Crear e instalar un gestor de seguridad
  • Crear y exportar uno o mas objetos remotos
  • Registrar al menos un objeto remoto con el registro RMI (o con otro servicio de nombe, como un sercio accesible a traves la interfaz Java Namin and Directory) como metodo de arranque.

A continuacion ponemos la implementacion del motor de computo. La clase engine.ComputeEngine implementa la interfaz remota Computo y tambien incluye el metodo main para iniciar el motor de computo. Aqui teneis el codigo fuentepara la clase ComputeEngine:

package engine;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import compute.Compute;
import compute.Task;

public class ComputeEngine implements Compute {

    public ComputeEngine() {
        super();
    }

    public <T> T executeTask(Task<T> t) {
        return t.execute();
    }

    public static void main(String[] args) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        try {
            String name = "Compute";
            Compute engine = new ComputeEngine();
            Compute stub = (Compute) UnicastRemoteObject.exportObject(engine, 0);
            Registry registry = LocateRegistry.getRegistry();
            registry.rebind(name, stub);
            System.out.println("ComputeEngine bound");
        } catch (Exception e) {
            System.err.println("ComputeEngine exception:");
            e.printStackTrace();
        }
    }
}

A continuación explicaremos cada elemento de la implementacion del motor de computo.

Declarando las interfaces remotas que serán implementadas.

La implementacion del motor de computo es declarada:

public class ComputeEngine implements Compute

Esta declaracion indica que implementamos la interfaz remota Computo y que pude ser usada par los objetos remotos.

La clase ComputeEngine define una implementacion de la clase del objeto remoto que implementa una unica interfaz remota. La clase ComputeEngine tambien contiene dos elementos executables que solo pueden ser invocados de forma local. El primero de esos elementos es el contructor para las instancias de ComputeEngine. El segundo es el metodo main que se usa para clerar la instacion de ComputeEngine que  hace que este disponible para los clientes.

Definiendo el constructor para un objeto remoto.

La clase ComputeEngine tiene un unico contructor que no toma ningun argumento. El codigo del constructor esta a continuación:

public ComputeEngine() {
    super();
}

Este constructor solo invoca al constructor de la superclase, el cual es un constructor sin argumentos de la clase Object. De todas formas el constructor de la superclase es invocado si fuera omitido por el constructor ComputeEngine, esto esta incluido para facilitar la comprension del codigo.

Creando las implementaciones para cada método remoto.

La clase para un objeto remoto implementa cada metodo remoto de la interfaz remota. La interfaz Compute contiene un unico metodo, executeTask, implementacion de la cual se muestra  a continuación

public <T> T executeTask(Task<T> t) {
    return t.execute();
}

Este metodo implementa el protocolo entre el objeto remoto ComputeEngine y sus clientes, ComputeEngine recibe de cada cliente un objeto Task con su implementacion para la interfaz Task y su metodo de ejecución. El ComputeEngine ejecuta cada tarea del cliento y devielve lo resultados de la ejecucion al cliente.

Pasando Objetos en RMI

Los argumentos o valores de retorno de los métodos remotos pueden ser de cualquier tipo, incluyendo objetos locales, objetos remotos y tipos de datos primitivos. De forma mas preciso cualquier entidad de cualquier tipo puede ser pasada o recibida desde un objeto remoto, un objero remoto, o un objeto serializable (lo que significa que implementa la interfaz java.io.Serializable).

Algunos tipos de objeto no cumple alguno de estos criterios y por lo tanto no pueden ser pasados o recibidos por un método remoto, Muchos de esos objetos, como threads o descriptos de archivos, encapsulan información que solo tiene sentido en un único espacio de memorio, Muchas de las clases del núcleo de java incluyendo las clases en los paquetes java.lang y java.util implementan la interface Serializable.

Las reglas que rigen las condiciones para que los argumentos o valores de retorno sean validos son las siguientes:
*Los objetos remotos se pasa esencialmente por referencia. Una referencia a un objeto remote es un stub, que es un proxy del lado del cliente que implementa el conjunto completo de interfaces que implementa un objeto remoto.
*Los objetos locales son pasados como una copia, usando serializacion de objetos. Por defecto , todos los campos son copiados excepto los que están marcados como static o transient, El comportamiento predeterminado de la serializacion pude ser sobrescrito.

Pasar un objeto remoto por referencia significa que cualquier cambio realizado en el estado del objeto por la invocación remota queda reflejado en lo objeto remoto original. Cuando un objeto remoto es pasado, solo las interfaces que son interfaces remotas están disponibles para el receptor. Cualquier motoso definido en la implementación de la clase o definido en las interfaces no remotas implementadas por la clase no estan disponibles para el receptor.

Por ejemplo, if estuvieramos pasando una referencia a una instancia de la clase ComputeEngine, el receptor solo tendria acceso al metodo executeTask. El receptor no veria el constructor de ComputeEngine, su metodo main o sun implementaciones de cualquier metodo de java.lang.Object.

En los parámetros y valores de retorno de las invocaciones remotas a metodos, los objetos que no son objetos remotos son pasados por valor, osea , una copia del objeto es creada en la maquina virtual receptora. Cualquier cambio en el estado del objeto por el receptor se ve reflejado unacamente en la copia del receptor, no en la instancia original enviada. Cualquier cambio en el estado del objeto realizado por el enviador se ve reflejado solo en la instancia original del envio, no en la copia del receptor.

Implementando el metodo main del Servidor

El metodo mas complejo de la implementacion de ComputeEngine es el metodo main. El metodo main es usado para iniciar el motor de computo y necesita realizar la inicializacion para preparar el servidor para aceptar llamadas de los clientes. Este metodo no es un metodo remoto, lo que significa que no puede ser invocado por una maquina virtual diferente. A causa que que el metodo main esta declarado como static, el metodo no esta asociado con el objeto o mejor dicho con la clase ComputeEngine.

Creando e instalando un gestor de seguridad

La primera tarea del metodo main es crear e instalar un gestor de seguridad (Security Manager), ue protege el aceso a los recursos del sistema de codigo no verificado que transcurre entre maquinas virtuales. Un gestor de seguridad determina que codigo descargado tiene acceso al sistema de archivos locales o puede realizar cualquier otra operación privilegiada.

Si un programa RMI no instala un gestor de seguridad, RMI no descargara clases (que no esten en su class path) para los objetos recibidos como argumentos o valores de retorno de los metodos remotos. Esta restricción nos asegura que las operaciones realizadas con condigo descargado estan sujetas a una politica de seguridad.

Aqui esta el codigo que crea e instala un gestor de seguridad:

if (System.getSecurityManager() == null) {
 System.setSecurityManager(new SecurityManager());
}

Haciendo los objetos remotos disponibles para los clientes

El metodo main clea una instancia de ComputeEngine y lo exporta para el entono de ejecucion de RMI con las sigioentes lineas


Compute engine = new ComputeEngine();
Compute stub =

(Compute) UnicastRemoteObject.exportObject(engine, 0);

El metodo estatico UnicastRemoteObject.exportObject exporta el objeto remodo pasado como parametro para que pueda recibir invocaciones de sus metodos remotos a traves de clientes remotos. El segundo argumento, un int, especifica que puerto TCP sera usado para escuchar solicitudes para las invocaciones remotas. Generalmente el valor es cero, que especifica el uso de un puerto anónimo. El puerto actual sera seleccionado por RMI en tiempo de ejecución o por el sistema operativo. De todas formas un valor distinto a  cero puede ser usado para especificar el puerto de escucha. Una vez que la invocación  a exportObject se ha realizado de forma satisfactoria, el objeto remoto ComputeEngine esta listo para recibir invocaciones remotas.

El metodo exportObject devuelve un stub del objeto remoto esportado. Fijate que el tipo de variable stub debe ser Compute, no ComputeEngine, porque el stub de un objeto remoto solo implementa las interfaces remotasde los objetos remotos exportados implementados.

El exportObject motodo declara que puede ignorar una RemoteException, que es un tipo de excepcion comprobada. El metodo main maneja esta exception con sus bloques try/catch. Si la excepcion no esta manejada de esta manera el metodo main debera ignorar (throws) la RemoteException si lo recursos necesarios no estan disponibles, como que el puerto este ocupado para otros objetivos.

Antes de que el cliente pueda invocar un metodo de un objeto remoto, primero se debe obtener una referencia al objeto remoto.  Para obtener esta referencian se puede hacer de la misma forma por la que cualquier referenca a un objeto es obtenida por el programa, como obtener l referencia como parte de un valor de retorno o como parte de una estructura de datos que contiene dicha referencia.

El sistema nos provee de un tipo de objeto remoto particular, el registro RMI, para encontrar referencias a otros objetos remotos. El registro RMI es un servicio de nombres de objeto que permite a los clientes obtener una referencia a un objeto remoto por su nombre. El registro es usado generalmente para encontrar el primer objeto remoto que el cliente RMI necesita usar. Ese primer objeto puede ser usado para encontrar otros objetos.

La interfaz java.rmi.registry.Registry es el API para registrar y buscar objetos remotos en el registro. La clase java.rmi.registry.LocateRegistry contiene metodos estaticos para sintetizar una referencia remota a un registro en una direccion de red particular (host y puerto). Estos metodos crean la referencia remota a un objeto que contiene la direccion de red pero sin realizar ninguna comunicacion remota. LacaleRegistry tambien contiene metodos estaticos para crear un nuevo registro en la maquina virtual actual, de todas formas este ejemplo no usa esos metodos. Una vez que el objeto remoto esta registrado en el registro RMI del host local, los clientes de cualquier host puede bscar el objeto remoto por su nombre, obteniendo ss referencias y luego invocar los metodos remotos del objeto. El registro puede ser compartido por todos los servidores de un host, o un unico proceso servidor puede crear su propio registro.

La clase ComputeEngine crea un nombre para el objeto con la siguiente linea:

String name = "Compute";

Este codigo añade el nombre al registro RMI del servidor. Este para se reliza antes de los siguientes comando

Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, stub);

La llamada a rebind realiza una llamada al registro RMI del host local. Como cualquier llamada remota, esta puede generar una RemoteExceptionque sera manejada en bloque catch del metodo main.

Ten en cuenta las siguientes condiciones el las llamadas a Registry.rebind:

  • La sobrecarga sin argumentos a LocateRegistry.getRegistry sintetiza una referencia a iun registroen el host local y en su puerto predeterminado,1099. Tu debes usar una sobrecarga que tiene un parametro int si el registro esta creado en un puerdo distinto al 1099.
  • Cuando se realia una invocacion al registro, se pasa un stub del objeto remoto en lugar de una copia del objeto remoto. Las implementaciones de objetos remotos, como las instancias de ComputeEngine, nunca abandonaran la maquina virtual donde fueron creadas. Asi que, cuando un cliente realiza una busqueda en un servidor de registro de objetos remotos, una copia del stub (boceto) es devuelta. Los objetos remotos generalente son mas efecientes pasados como una referencia remota en lugar que por valor
  • Por razones de seguridad, una aplicacion solo puede realizar operaciones bind, unbind o rebind con referencias a objetos con un registro ejecutandosse en el mismo host. Esta restriccion nos ayuda a evitar que un cliente remoto borre o sobreescriba alguna estrada del servidor de registro. De todas formas una lookup (busqueda), puede ser solicitada por cualquier host, local o remoto.

Una vez que el servidor ha sido registrado con el registro local RMI, muestra un mensaje indicando que esta listo para empezar a manejar llamadas. Entonces, el metodo main se completa. No es necesario usar threads para mantener el servidor manejando escuchas.Mientras exista referencia al objeto ComputeEngine en otra maquina virtual, local o remota, el objeto ComputeEngine no se destruirá ni le afectara el recolector de basura, Porque el programa maneja una referencia a ComputeEngine que esta en el registro, que es accesible por el cliente remoto. El sistema RMI mantiene mantiene los procesos ComputeEngine ejecutandose. El ComputeEngine esta disponible para aceptar llamadas y no será utilizado hasque que su enlace sea eliminado por el registro y los clientes no remotos rompan la referencia remota al objeto CompteEngine.

La ultima porción de código en el método  ComputeEngine.main manejo cualquier posible excepción. El único tipo de excepción comprobada que puede ser ignorada en el código es la RemoteException, a través la llamada a UnicastRemoteObject.exportObject o por la llamada al método rebind. De cualquier forma, el programa no puede hacer mucho mas que salir después de imprimir un mensaje de error. En algunas aplicaciones distribuidas es posible recuperarse del fallo para realizar llamadas remotas. Por ejemplo, la aplicación podría hacer un reintento o seleccionar otro servidor para continuar funcionando.

Creando un programa Cliente

El motor de computo (compute engine) es un programa relativamente simple. Ejecuta tareas que son manejadas para eso. Los clientes de motor de computo son mas complejos. Un cliente necesita llamar al motor de computo, pero también tiene que definir las tareas que se ejecutarán en el motor de computo.
Dos clases separadas forman el cliente de nuestro ejemplo. La primera clase, ComputePi, busca e invoca un objeto Compute. La segunda clase, Pi, implementa la interfaz Task y define el trabajo para ser realizado por el motor de computo. El trabajo de la clase Pi es computar el valor de algunos decimales de Pi .

La interfaz no remota Task esta definida a continuación:

package compute;

public interface Task<T> {
 T execute();
}

Aquí estas el código fuente para cliente-ComputePi (link) :

<pre>package client;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.math.BigDecimal;
import compute.Compute;

public class ComputePi {

 public static void main(String args[]) {
 if (System.getSecurityManager() == null) {
 System.setSecurityManager(new SecurityManager());
 }
 try {
 String name = "Compute";
 Registry registry = LocateRegistry.getRegistry(args[0]);
 Compute comp = (Compute) registry.lookup(name);
 Pi task = new Pi(Integer.parseInt(args[1]));
 BigDecimal pi = comp.executeTask(task);
 System.out.println(pi);
 } catch (Exception e) {
 System.err.println("ComputePi exception:");
 e.printStackTrace();
 }
 }
}

Igual que el servidor ComputeEngine, el cliente comienza instalando un gesto de seguridad. Este paso es necesario porque durante el proceso de recibir los borradores (stub) de los objetos remotos del servidor puede ser necesario descargar las definiciones de clases del servidor. Para que RMI descargue clases el gesto de seguridad debe ser forzado.
Después de instalar el gestor de seguridad, el cliente construye un nombre para realizar las búsquedas de los objetos remotos Compute, usando el mismo nombre que usa ComputeEngine para unirse con el cliente. También el cliente usa la API LocaleRegistry.getRegistry para sintetizar una referencia remota para registras el host remoto. El valor de primer argumento de los argumentos pasados por consola, args[0], es el nombre del host remoto en el que se ejecuta el objeto Compute. Entonces el cliente invoca al método lookup en el registro para buscar el objeto remoto por nombre en el registro del host servidor. La sobrecarga particular de LocateRegistry.getRegistry  que solo tiene un parámetro una String, devuelve una referencia al registro del host remoto en el puerto 1099. Si el puerto del servidor es distinto al 1099 debes usar la sobrecarga que tiene un parámetro int.

A Continuación el cliente crea un nuevo objeto Pi, pasando al constructor de pi el valor del segundo argumento de los argumentos de la linea de comandos, args[1], pasada como un entero. Este argumento indica el numero de valores decimales para ser calculados. Finalmente el cliente invoca al método executeTask recibiendo un objeto del tipo BigDecimal, que el programa almacena en la variable result. El siguiente gráfico describe el flujo entre el cliente ComputePi, el rmiregistry (registro mi) y el ComputeEngine (motor de computo).

Flujo elementos RMI

La clase Pi implementa la interfaz Task y calcula el valor de un numero de decimales de Pi. Para este ejemplo, el algoritmo no es importante. Lo que si es importante del algoritmo es su coste computacional lo que significa que se deberá ejecutar en un servidor capacitado.
Aquí esta el código fuente para el cliente.Pi la clase que implementa la interfaz Task:

</pre>
package client;
import compute.Task;

import java.io.Serializable;

import java.math.BigDecimal;
public class Pi implements Task<BigDecimal>, Serializable {
 private static final long serialVersionUID = 227L;
 /** constants used in pi computation */

private static final BigDecimal FOUR =

BigDecimal.valueOf(4);
 /** rounding mode to use during pi computation */

private static final int roundingMode =

BigDecimal.ROUND_HALF_EVEN;
 /** digits of precision after the decimal point */

private final int digits;
 /**

* Construct a task to calculate pi to the specified

* precision.

*/

public Pi(int digits) {

this.digits = digits;

}
 /**

* Calculate pi.

*/

public BigDecimal execute() {

return computePi(digits);

}
 /**

* Compute the value of pi to the specified number of

* digits after the decimal point.  The value is

* computed using Machin's formula:

*

*          pi/4 = 4*arctan(1/5) - arctan(1/239)

*

* and a power series expansion of arctan(x) to

* sufficient precision.

*/

public static BigDecimal computePi(int digits) {

int scale = digits + 5;

BigDecimal arctan1_5 = arctan(5, scale);

BigDecimal arctan1_239 = arctan(239, scale);

BigDecimal pi = arctan1_5.multiply(FOUR).subtract(

arctan1_239).multiply(FOUR);

return pi.setScale(digits,

BigDecimal.ROUND_HALF_UP);

}

/**

* Compute the value, in radians, of the arctangent of

* the inverse of the supplied integer to the specified

* number of digits after the decimal point.  The value

* is computed using the power series expansion for the

* arc tangent:

*

* arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 +

*     (x^9)/9 ...

*/

public static BigDecimal arctan(int inverseX,

int scale)

{

BigDecimal result, numer, term;

BigDecimal invX = BigDecimal.valueOf(inverseX);

BigDecimal invX2 =

BigDecimal.valueOf(inverseX * inverseX);
 numer = BigDecimal.ONE.divide(invX,

scale, roundingMode);
 result = numer;

int i = 1;

do {

numer =

numer.divide(invX2, scale, roundingMode);

int denom = 2 * i + 1;

term =

numer.divide(BigDecimal.valueOf(denom),

scale, roundingMode);

if ((i % 2) != 0) {

result = result.subtract(term);

} else {

result = result.add(term);

}

i++;

} while (term.compareTo(BigDecimal.ZERO) != 0);

return result;

}

}
<pre>

Notese que todas las clases serializables, aquellas que implementan las interfaces serializable directa o indirectamenta, deben declarar un campo private static final llamado seriaVersionUID para garantizar la compativilidad entre versiones. Si no en existe una versión previa de la clase, entonces el valor de este campo puede ser cualquier valor long, similar al de 227L usado por pi, segun la longitud del valor sera usado en versiones futuras. Si existiese una versión previa de la clase si una declaracion explicita de serialVersionUID , pero la compatibilidad con la versión anterior es importante, entonce el valor implícito predeterminado para computar sera el que debera ser usado para el valor de la nueva versión. La herramienta serialver puede determinar el valor predeterminado a usar.

La caracteristica mas importante de este ejemplo es que la implementación del objeto value nunca necesita la definición de la clase Pi hasta que el objeto es pasado como argumento al metodo executeTask. En ese punto, el codigo de la clase es cargado por RMI en la maquina virtual del Objeto Compute, el metodo execute es invocado, y el codigo de la tarea es ejecutado. El resultado, que en el caso de la tarea Pi es un objeto BigDecimal, es retornado al cliente que realizao la llamado, donde es usado para imprimir el resultado del computo.

El hecho de que el objeto Task  compute el valor de Pi es irrelevante para el objeto ComputeEngine. Tu tambien podrias implementar una task que, por ejemplo, generase un numero primo aleatoria. Cualquier tarea podria se intensiva desde el punto de vista computacional  seria una buena candidata para el ComputeEngine, pero requeriria un codigo muy diferente. Este codigo tambien podria ser descargado cuando un objeto Task es pasado a otro Compute. a causa de que el objeto Compute no necesita saber lo que la implementación de Task hace.

proximo post (como poner todo esto en marcha)

Practica 3 ASO

1. (Kernel Lista) Modifica la cabecera “include/linux/list.h” del kernel para que se pueda

utilizar en un programa de usuario. Escribe un programa que utiliza las funciones de listas enlazadas dentro de list.h para:

  • insertar números aleatorios.
  • recorrer la lista imprimiendo los valores.
  • eliminar un nodo de la lista (utilizando un menú de selección).

2. (Simulador de Procesos) En este problema, queremos estudiar el efecto de diferentes
parámetros relacionado con “timeslice” a diferentes algoritmos de planificación. Escribe un
programa que es simula el comportamiento del gestor de planificación con diferentes valores
de timeslice y para diferentes cargas de cambio de contexto de procesos. Para ello debe
seguir los siguientes pasos:
a) Utilizando su libraría de funciones que ha creado en practicas anteriores, genera los
siguientes datos para procesos que van a querer utilizar el CPU: (i) el PID de cada
procesos, un número aleatorios que representa el tiempo de llegada, y un numero
aleatorio que representa el tiempo total que va a ejecutar en el CPU. Como ejemplo,
los números puede ser como las siguientes:
PID T_llegada            T_total
1        30      0.783560
2         54     17.282004
3         97     32.814522
Que significa que el primer proceso llega a 30 segundos y quiere 0.783560 segundos para ejecutar, el segundo proceso llega a t=54 segundos y necesita 17.28 segundos para ejecutar, ect.
b) Escribe un función que dado los valores generado, es capaz de contar el timeslice y
utilizar planificación de “preemption”, si necesario, para intercambiar procesos cuando
el timeslice de un proceso se agota.
c) Escribe un algoritmo de político “Round Robin”.
d) Escribe un función que calcula el tiempo media de espera y el tiempo media de la tasa de terminar para todos los procesos.
e) Ejecuta su simulación para tiempos de sobrecargo de cambio de contexto de 0, 5, 10, 15, 20 y 25 milisegundos; y por valores de timeslice de: 50, 100, 250, y 500
milisegundos. Hacer gráficos (plots) de lo que encuentras.

Lo primero que tenemos que hacer es copiar la libreria list.h a un archivo nuevo (el kernel de linux no esta en C estándar) y compilar para ver si lo acepta.

Al primer intento nos va a decir que no por las librerías así que tendremos que borrarlas del código

//#include <linux/poison.h>
//#include <linux/prefetch.h>
//#include <asm/system.h>

Volvemos a compilar y tenemos problemas con las variables LIST_POISON esto se produce en las siguientes dos funciones:

  • funcion1

static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
//entry->next = LIST_POISON1;
//entry->prev = LIST_POISON2;
}

  • funcion2

static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
//n->next = LIST_POISON1;
//n->pprev = LIST_POISON2;
}

Así  ya nos compila el código.

El uso de las listas del kernel difiere del uso clásico que tenemos en mente.

Diagrama clasico de la estructura de una lista
Diagrama clásico de la estructura de una lista

aquí tenemos el esquema de uso de una kernel list

comportamiento de una kernel list
comportamiento de una kernel list

la principal diferencia es que los enlaces de la lista son una estructura dentro de nuestra estructura, por lo tanto no nos movemos a través de nuestra lista sino que vamos accediendo a partes internas de la lista. El principal problema de utilizar este método es acceder a la estructura que contiene los enlaces, esto se realiza mediante el calculo del offset de un puntero.

/*
* getCustomListPointer — gets the customlist memory address from a listPointer calculating the offsett
* listPointer — a pointer that point a list element
*/

struct customList *getCustomListPointer(struct list_head *listPointer)//DONE
{
void * toret=NULL;
toret=listPointer;
//We use a void pointer because i can’t sobrem problems with pointers aritmetic
toret= (toret – ((unsigned long) &((struct customList *)0)->list));
return toret;
}

Toret es un puntero a  void para evitar problemas en la aritmética de punteros, si este fuera un char puntero -1 seria iguar a puntero -1(tamaño char) por lo que tendríamos problemas de fallo de segmento.

La estructura del código se puede observar en el siguiente esquema:

Organización del simulador de procesos
Organización del simulador de procesos

Existen unos pequeños bugs y características no implementadas en la aplicación

  • El iterador usa variable global que puede sufrir efectos laterales (las funciones copyCustomList tiene el problema arreglado al ser recursivas y utilizar un registro como indicador de fin de recursividad)
  • Habría que mirar el tamaño de una variable void* (si es >1 produce segmentation fault por mal calculo de offset)
  • Añadir elemento y otras funciones no esta implementado solo seria añadir una sucesión de printf y scanf en el código.
  • No esta implementado el paso de parámetros como por ejemplo establecer el numero de procesos que se simularan (cambiar 15000, por una variable en linea 113 de main.c)
Codigo Fuente
Codigo Fuente

Funcionamiento:

La ejecución muestra por pantalla los datos de cada proceso, timeslice y contextChangue según termina cada proceso,  se ha definido un conjunto de 15000 procesos para sacar estadísticas.

Los ejecución recomendada es ./ejecutable> salida.cvs siendo salida.cvs un archivo comma separated values que se importara a mysql para realizar calculos de forma mas sencilla. La definición de la tabla que se usara esta en el siguiente enlace (Database struct Definitión)

Una vez obtenida la salida la importación a MySql se realiza ejecutando un orden similar a esta.

LOAD DATA LOCAL INFILE’/home/luzem/NetBeansProjects/Practica3/dist/Debug/GNU-Linux-x86/salida.csv’
INTO TABLE roundrobin
FIELDS TERMINATED BY ‘,’
LINES TERMINATED BY ‘\n’

Con esto y un conjunto de consultas SQL podemos obtener los datos para procesar en GNUPLOT.

Gráficas

ContextChangue effects
Como Afecta el ContextChangue en la media global

En  la anterior gráfica podremos ver los efectos del incremento del contextChangue sobre el tiempo medio de espera, observando como el impacto es independiente del timeslice.

Tiempo medio de espera
Tiempo medio de espera

El tiempo medio de espera de cada proceso aumenta en función de timeslice y dada que la diferencia entre timeslice y contextchangue es muy alta es el aumento del timeslice quien castiga mas a los tiempos de espera.

En cambio si tenemos en cuenta la media del tiempo total de espera para los conjuntos de timeslice y contextchangue obtenemos la siguiente media

Impacto sobre el la media del tiempo total de espera
Impacto sobre el la media del tiempo total de espera

Cuando el timeslice es muy pequeño el numero de cambios de contexto aumenta penaliza el tiempo total de espera de una forma mas que considerable.

Si extraemos el 15% inicial y el 15% final y calculamos las medias para cada segmento obtenemos las siguiente grafica

Differences between short long process
Differences between short long process

En la anterior gráfica observamos que el impacto sobre la media de tiempo de espera, afecta mayormente a la parte central del conjunto de procesos.

Mejoras:

Utilizar varias listas round robin con diferente timeslice  y mover los elementos customList en función del contador de paradas (timeslice grande para procesos largos y timeslice pequeño para procesos cortos)