Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Menu

Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menu

Temas - NeCRoMaNCeR

#1
Programación gráfica / Nuevo Rpg
15 de Agosto de 2005, 05:46:34 PM
 Buenas stratomaniacos :D  tengo el agrado de comentar que entre varios personajes de mi ciudad en Argentina estamos con el desarrollo de nuestro primer videojuego, dibujantes, diseñadores 3d, un programador y yo que diseño y programo un poquitin.
Estoy organizando la base del juego y su historia, tambien diseñando mucho y leyendo sobre el correcto ensamblaje de mallas.
El rpg sera mas o menos del estilo de diablo pero en 3D (sin imagenes prerenderizadas) y con una visual estilo GTA de camara en tercera persona rotable, algo como lo nuevo de www.aztlanrpg.net .
Queria que por favor me dieran algunos consejos y me contesten las siguiente pregunta...

¿Cual seria la forma mas adecuada para que los personajes cambien armaduras , yelmo y botas sin necesidad de animar como objetos tenga? Yo pensé que con programación colocando correctamente la armadura en y borrando los polys tapados por la misma para ahorrar recursos.¿estoy en lo correcto?

Saludos camaradas...

PD: El juego no será comercial, por lo menos en su primera versión, a pesar de la magnitud de la idea es solo para aprender y tener como referencia en un demoreel y curriculum.
#2
Programación gráfica / Un Consejo.
30 de Marzo de 2005, 03:11:46 AM
 Buenas a todos los stratomaniacos, necesito un consejo para un personaje en un juego.
resulta que el personaje es un brujo y ya le puse huesos , ahora en lo que no me decido es si ponerle el baculo como parte de la malla , o que se lo agregue el programador con codigo. Que me recomiendan?
Saludos!
#3
Programación gráfica / Poligonaje
01 de Marzo de 2005, 07:40:34 AM
 Buenas, tengo un personaje low poly para el juego en que estoy trabajando y sera para maquinas potentes(amd 2.16 gb gforce 64mb o 128mb y 512 mb de ram aproximadamente los mismos requerimentos de doom3)bueno este personaje tiene 15.000 polys al poseer 8 patas y una coraza; es recomendable usar este personaje?
#4
Programación gráfica / Ayuda Get_movements Please!
01 de Marzo de 2005, 05:03:07 AM
 Buenas , Tengo este personaje que es un alien y la voy a haer jugable , quisiera saber como es que se hace normalmente en los motores graficos en pocas palabras ; como se logra que el personaje camine pero sin distorcionar la caminata pueda mirar hacia arriva y hacia abajo.
Uso el Ogre3d engine.
                                                      Saludos!


#5
Programación gráfica / Robots A C++ ?
02 de Febrero de 2005, 09:21:59 AM
 Buenas, Tengo una duda, estoy diseñando un videojuego high poly y quiero introducir robots a base de sistemas mecanicos , es posible esto?
Ya que por lo que vi y estudie los engines basados en directx y opengl necesitan si o si bones para reconocer movimiento de vertex´s.
                                                                                     Saludos.
#6
General Programadores / Malditos Arboles B
14 de Marzo de 2005, 12:47:07 PM
Venga, a ver si te sirve esto 8) Suerte!

[code]
#define LLENO 3

/****************************************************************
* TIPOS DE DATOS
*************************************************************/


typedef struct tag_clave
{
   /* Datos del registro que estamos indexando, el offset que
   tiene en la bd original, el tamaño en bytes de la clave
   y un puntero a los bytes de dicha clave */
   long offset;
   int tam_clave;
   void *clave;
   
}CLAVE;

typedef struct tag_pagina
{
   
   /* Datos de una pagina */
   int contador_claves;   /* Numero de claves que tiene la pagina, max orden-1 */
   int numero_pag;         /* El numero de la pagina dentro de la bd, no es demasiado util */
   long offset;            /* el offset de la pagina en la bd */
   long padre;             /* el offset del padre de esta pagina en la bd, -1 si no hay (raiz) */
   long *hijos;            /* array de longs que contiene los hijos de esta pagina. Si es una
                                  pagina hija lo sabremos porque hijos[0] sera -1*/
   
   /* Array con los punteros a las claves de la pagina */
   CLAVE **claves;
   
   
}PAGINA;


/****************************************
      Crea_ArbolB
Descripcion:
   Crea una base de datos de indices de arbolb con un orden y un tamano
   maximo de clave dado (ya que utiliza registros de tamano fijo).
     
Entradas:
   **bdarbol: puntero a una estructura de tipo BDFichero previamente localizada
      que contendra la informacion del arbolb
   *farbolb: nombre del fichero en el que se guardara la bd
   *orden: orden (numero maximo de ramas) del arbolb a usar
   tam_clave: tamano maximo de las claves que contendra el arbol
   *funcmp: funcion de comparacion a usar
   

Salidas:
   codigo de error
Notas:
   

****************************************/

int Crea_ArbolB( BDFichero **bdarbol, char *farbolb, int orden, int tam_clave, void *funcmp)
{
   
   BDFichero *arbol=NULL;
   int i=0;
   PAGINA *pagina_arbol=NULL;
   
   /*
   Calculamos el tamano del registro mas grande que crearemos, sumando:
   el tamano base de una pagina, el tamano del array con todos los offsets de las claves,
   el tamano del array de las claves y el tamano del array con los offsets de los hijos.
   y le anadimos 2 bytes del indicador de estado del registro */
   int max_tam=sizeof(PAGINA) + ( (orden-1) * sizeof(CLAVE)) + ((orden-1) * tam_clave) + \
   ( orden * sizeof(long)) + 2;

   
   /* CdE */
   if ( bdarbol == NULL || farbolb == NULL )
   {
      printf("Error en los parametros de Crea_ArbolB\n");
      return ERR;
   }
   
   
      
   /* Creamos una pagina inicial vacia para hacer la raiz */
   if ( Crea_Pagina(&pagina_arbol, orden,-1) == ERR )
   {
      printf("Error creando pagina vacia en Crea_ArbolB\n");
      if ( pagina_arbol ) Libera_Pagina(pagina_arbol, orden);
      return ERR;
   }
   
   
      
   arbol=BDCrea(farbolb, BD_FIJO, max_tam);
   
   /* Inicializamos los tamaños de la bd de indices arbolb */
   
   memcpy ((arbol->pCabecera)->sRelleno, &max_tam, 4);
   i = arbol->lPosicionActual;
   memcpy (&((arbol->pCabecera)->sRelleno[4]), &i, 4);
   i = orden;
   memcpy (&(arbol->pCabecera->sRelleno[8]), &i, 4);
   /* Escribimos la direccion de la funcion de comparacion a usar en la cabecera */
   /* Esperemos que esto funcione..........................................      */
   memcpy (&(arbol->pCabecera->sRelleno[12]), funcmp, sizeof(void*));
   i = 0;
   memcpy (&(arbol->pCabecera->sRelleno[16]), &i, sizeof(int));
   
   if ( BDEscribe_Pagina(arbol, pagina_arbol, -1) == ERR )
   {
      printf("Error insertando pagina vacia en Crea_ArbolB\n");
      if ( pagina_arbol != NULL ) free(pagina_arbol);
      return ERR;
   }
   
   Libera_Pagina(pagina_arbol, orden);
   /* marcamos que hemos actualizado el arbol*/
   (arbol->pCabecera)->sRelleno[217]='$';
   (arbol->pCabecera)->sRelleno[216]='$';
   (arbol->pCabecera)->sRelleno[215]='$';

   if ( BDCierra(arbol)==ERR )
      printf("Error cerrando la bd creada en crea_arbolb\n");
      

   if ( Abrir_BaseD( bdarbol, farbolb)==ERR)
   {
      printf("Error reabriendo la bd recien creada, debio de haber error creandola\n");
      return ERR;
   }
   
   
   
   return OK;

}


/****************************************
      BDEscribe_Pagina
Descripcion:
   Escribe una pagina dada en una posicion dada
   
   
Entradas:
   *bdarbol: base de datos de un indice tipo arbolb a usar
   *pag: pagina previamente localizada y rellenada (o actualizada) a insertar (o modificar)
   posicion: offset en el archivo en el cual escribir el registro
   
Salidas:
   codigo de error

Notas:
   Si la posicion es -1, inserta la pagina en la bd como si fuera nueva
   (aprovechando los posibles huecos)
   

****************************************/

int BDEscribe_Pagina( BDFichero *bdarbol, PAGINA *pag, long posicion)
{
   int tamano=0, i=0;
   void  *aux=NULL;
   int orden=0;
   unsigned short int no_vacio=1;
   
   if ( bdarbol == NULL || pag == NULL )
   {
      printf("Error en los parametros de BDEscribe_Pagina\n");
      return ERR;
   }
   
   if ( bdarbol->pCabecera->iTipoBD != BD_FIJO )
   {
      printf("Tipo de bd erronea, solo usamos BD_FIJO\n");
      return ERR;
   }
   
   memcpy( &orden, &(bdarbol->pCabecera->sRelleno[8]), sizeof(int));
   
   
   
   /* Comprobamos que el tamanoo de la bd sea adecuado */
   memcpy(&tamano, bdarbol->pCabecera->sRelleno, sizeof(int));
   
   if ( tamano < sizeof(PAGINA) )
   {
      printf("Error, el tamano de los registros de la bd es menor que el de la pagina\n");
      return ERR;
   }
      
   
   aux=bdarbol->pRegistroActual;
   
   /* Anadimos dos bytes indicando que el registro NO esta vacio */
   memcpy(bdarbol->pRegistroActual, &no_vacio, 2);
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+2;
      
   /* Añadimos el numero de claves en la pagina */
   memcpy(bdarbol->pRegistroActual, &(pag->contador_claves), sizeof(int));
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(int);
   
   /* Añadimos el numero de pagina */
   if ( pag->numero_pag == -1 )
   {
      /* Si se paso una pagina nueva, le ponemos el ultimo numero de pagina disponible */
      memcpy( &i, &(bdarbol->pCabecera->sRelleno[16]), sizeof(int));
      memcpy( &(pag->numero_pag), &i, sizeof(int));
      i++;
      memcpy( &(bdarbol->pCabecera->sRelleno[16]), &i, sizeof(int));
   }
   memcpy(bdarbol->pRegistroActual, &(pag->numero_pag), sizeof(int));
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(int);

   /* Añadimos la posicion del padre */
   memcpy(bdarbol->pRegistroActual, &(pag->padre), sizeof(long));
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(long);

   /* Anadimos la posicion de la pagina */
   if ( posicion > -1 ) memcpy(bdarbol->pRegistroActual, &posicion, sizeof(long));
   else memcpy(bdarbol->pRegistroActual, &(pag->offset), sizeof(long));
   bdarbol->pRegistroActual+=sizeof(long);
   
   /* Escribimos todos los offsets de los hijos (esten vacios o no ) */
   memcpy(bdarbol->pRegistroActual, pag->hijos, sizeof(long)*orden);
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+(sizeof(long)*orden);
   
   
   /* Escribimos las claves contenidas en la pagina */
   for( i = 0; i < pag->contador_claves; i++)
   {
      if ( pag->claves == NULL  )
      {
         printf("Pagina corrupta en BDEscribe_Pagina\n");
         return ERR;
      }   
   
      memcpy(bdarbol->pRegistroActual, &(((CLAVE*)pag->claves[i])->offset), sizeof(long));
      bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(long);
   
      
      memcpy(bdarbol->pRegistroActual, &(((CLAVE*)pag->claves[i])->tam_clave), sizeof(int));
      bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(int);
         
      memcpy(bdarbol->pRegistroActual, ((CLAVE*)pag->claves[i])->clave, ((CLAVE*)pag->claves[i])->tam_clave);
      bdarbol->pRegistroActual=bdarbol->pRegistroActual+((CLAVE*)pag->claves[i])->tam_clave;
   
               
   }
      
   bdarbol->pRegistroActual=aux;
         

   
   if ( posicion == -1 )
   {   
      if( BDAniadeRegistro(bdarbol)==ERR )
      {
         printf("Error al escribir pagina como un nuevo registro en BDEscribe_Pagina\n");
         return ERR;
      }
      /* Tenemos que averiguar el offset en el que se guardo la pagina! */
      aux=bdarbol->pRegistroActual;
      pag->offset = bdarbol->lPosicionActual-tamano;
      bdarbol->lPosicionActual -= tamano;
      bdarbol->pRegistroActual = bdarbol->pRegistroActual + ( 2 + (sizeof(int)*2)+sizeof(long));
      memcpy(bdarbol->pRegistroActual, &(pag->offset), sizeof(long));
      bdarbol->pRegistroActual = aux;
      if ( BDPonte(bdarbol, bdarbol->lPosicionActual, 0)==ERR)
      {
         printf("Error posicionando en BDEscribe_Pagina\n");
         return ERR;
      }
      
      if( BDEscribeRegistro(bdarbol) == ERR )
      {
         printf("Error escribiendo registro en la posicion indicada en BDEscribe_Pagina\n");
         return ERR;
      }
      
      
      
   }
   else if ( posicion > -1 )
   {
      
      bdarbol->lPosicionActual = posicion;
      
      if ( BDPonte(bdarbol, bdarbol->lPosicionActual, 0)==ERR)
      {
         printf("Error posicionando en BDEscribe_Pagina\n");
         return ERR;
      }
      
      if( BDEscribeRegistro(bdarbol) == ERR )
      {
         printf("Error escribiendo registro en la posicion indicada en BDEscribe_Pagina\n");
         return ERR;
      }
      /* Nos quedamos donde hayamos terminado de escribir (el siguiente registro ) */
      /* bdarbol->lPosicionActual = aux; */
   }
   
   return OK;
}

/****************************************
      BDLee_Pagina
Descripcion:
   Lee una pagina desde una posicion dada
   
   
Entradas:
   *bdarbol: base de datos de un indice tipo arbolb a usar
   *pag: pagina previamente localizada en la que leer los datos del registro de la bd
   posicion: offset en el archivo desde el cual leer la pagina
   
Salidas:
   codigo de error

Notas:
   Devuelve vacio si el registro no contenia informacion

****************************************/
int BDLee_Pagina ( BDFichero *bdarbol, PAGINA *pag, long posicion)
{
   int estado=ERR, i=0;
   void  *aux=NULL;
   int orden=0;
   long pos=0;
   
   if ( bdarbol == NULL || pag == NULL )
   {
      printf("Error en los parametros de BDLee_Pagina\n");
      return ERR;
   }
   
   if ( bdarbol->pCabecera->iTipoBD != BD_FIJO )
   {
      printf("Tipo de bd erronea, solo usamos BD_FIJO\n");
      return ERR;
   }
   
   if ( posicion < (sizeof(BDCabecera)-1))
   {
      printf("Error en los parametros de BDLee_Pagina\n");
      return ERR;
   }
   
   
   memcpy( &orden, &(bdarbol->pCabecera->sRelleno[8]), sizeof(int));
   pos = bdarbol->lPosicionActual;
   aux=bdarbol->pRegistroActual;
   
   if ( BDPonte(bdarbol, posicion ,0)==ERR)
   {
      printf("Error posicionando la bd en BDLee_Pagina\n");
      return ERR;
   }
   
   estado = BDLeeRegistro( bdarbol );
   if (  estado == ERR )
   {
      printf("No se pudo leer el registro de la pagina en BDLee_Pagina\n");
      BDPonte(bdarbol,pos,0);
      return ERR;
   }
   else if ( estado == VACIO )
      return VACIO;
   
   /* Saltamos el indicador de registro no vacio */
   bdarbol->pRegistroActual+=2;
      
      
   /* Leemos el numero de claves en la pagina */
   memcpy(&(pag->contador_claves),bdarbol->pRegistroActual, sizeof(int));
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(int);
   
   /* Leemos el numero de pagina */
   memcpy(&(pag->numero_pag), bdarbol->pRegistroActual,  sizeof(int));
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(int);

   /* Leemos la posicion del padre */
   memcpy(&(pag->padre), bdarbol->pRegistroActual, sizeof(long));
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(long);

   /* Leemos la posicion de la pagina */
   memcpy(&(pag->offset), bdarbol->pRegistroActual, sizeof(long));
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(long);
   
   /* Leemos todos los offsets de los hijos (esten vacios o no ) */
   memcpy(pag->hijos, bdarbol->pRegistroActual,sizeof(long)*orden);
   bdarbol->pRegistroActual=bdarbol->pRegistroActual+(sizeof(long)*orden);
   
   /* Leemos el array de punteros a clave */
   
   /*
   memcpy(pag->claves, bdarbol->pRegistroActual, sizeof(CLAVE*)*(orden-1));
   bdarbol->pRegistroActual+=sizeof(CLAVE*)*(orden-1);
   */
   
   
   /* Leemos las claves contenidas en la pagina */
   for( i = 0; i < pag->contador_claves; i++)
   {
   
      if ( pag->claves == NULL )
      {
         printf("Pagina corrupta en BDEscribe_Pagina\n");
         return ERR;
      }   
      
      if ( ( pag->claves[i] = (CLAVE*) calloc( 1, sizeof(CLAVE)))==NULL)
      {
         printf("Error localizando espacio para la clave en BDLee_Pagina\n");
         BDPonte(bdarbol,pos, 0);
         return ERR;
      }   
      
      memcpy(&(((CLAVE*)pag->claves[i])->offset), bdarbol->pRegistroActual,sizeof(long));
      bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(long);
   
      
      memcpy(&(((CLAVE*)pag->claves[i])->tam_clave), bdarbol->pRegistroActual,  sizeof(int));
      bdarbol->pRegistroActual=bdarbol->pRegistroActual+sizeof(int);
      
      
      if ( ( ((CLAVE*)pag->claves[i])->clave = (void*) malloc(((CLAVE*)pag->claves[i])->tam_clave))==NULL)
      {
         printf("Error reservando memoria para clave en BDLee_Pagina\n");
         BDPonte(bdarbol,pos,0);
         return ERR;
      }
         
      memcpy(((CLAVE*)pag->claves[i])->clave, bdarbol->pRegistroActual,  ((CLAVE*)pag->claves[i])->tam_clave);
      bdarbol->pRegistroActual=bdarbol->pRegistroActual+((CLAVE*)pag->claves[i])->tam_clave;
   
   }
      
   bdarbol->pRegistroActual=aux;
   return OK;

}

/****************************************
      BDBorra_Pagina
Descripcion:
   Borra una pagina dada de la bd en disco
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   posicion: posicion de la pagina en la bd
   num_pag: numero de la pagina en la bd

Salidas:
   codigo de error
Notas:
   Borramos o por posicion o por numero de pagina

****************************************/

int BDBorra_Pagina( BDFichero *bdarbol, long posicion, int num_pag)
{
   long pos=0;
   /* CdE */
   if ( bdarbol == NULL || ( posicion < 0 && num_pag < 0 ))
   {
      printf("Error en los parametros en BDBorra_Pagina\n");
      return ERR;
   }
   
   if ( num_pag > -1 ) pos = Busca_Sec_Pagina( bdarbol, num_pag );
   else pos = posicion;
   if ( pos == -1 )
   {
      printf("No se pudo hallar la posicion de la pagina a borrar en BDBorra_Pagina\n");
      return ERR;
   }
   
   if ( BDPonte(bdarbol, pos, 0) == ERR )
   {
      printf("Error posicionando bd en BDBorra_Pagina\n");
      return ERR;
   }
   
   if ( BDBorraRegistro(bdarbol)== ERR )
   {
      printf("Error borrando registro en BDBorra_Pagina\n");
      return ERR;
   }
   return OK;
}
   
/****************************************
      Inserta_Clave
Descripcion:
   Inserta una clave dada en el arbol
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   *clave: puntero a una clave a insertar previamente creada

Salidas:
   codigo de error
Notas:
   Siempre que vengamos de una promocion, nodo contiene al padre donde
   queremos promocionar al valor medio contenido en nuevo

****************************************/


int Inserta_Clave( BDFichero *bdarbol, CLAVE *clave)
{
   int indice_clave=0, indice_posible=0, hecho=0;
   int orden=0;
   long posicion=0;
   PAGINA *nodo=NULL, *nuevo=NULL, *padre=NULL;
   

   /* CdE */
   if ( bdarbol == NULL || clave == NULL )
   {
      printf("Error en los parametros de Inserta_Clave\n");
      return ERR;
   }
   
   memcpy(&orden, &(bdarbol->pCabecera->sRelleno[8]),sizeof(int));
   if ( orden < 1 )
   {
      printf("Error en la bd del indice arboreo\n");
      return ERR;
   }
   
   /* Buscamos la clave en el arbol, para descartar repeticiones */
   if ( Busca_Clave(bdarbol, &nodo, clave->clave, 0, -1,  &indice_posible, &indice_clave, 0)== ERR )
   {
      printf("Error buscando clave en el arbol en Inserta_Clave\n");
      return ERR;
   }
   
   if ( indice_clave > -1 )
   {
      printf("Intento de insercion de clave presente\n");
      free ( clave->clave);
      free( clave );
      return ERR;
   }
   
   if ( indice_posible == -1 )
   {
      printf("BD erronea u otro error en Inserta_Clave\n");
      return ERR;
   }
   
   while ( hecho == 0 )
   {
      /* Hay hueco en la pagina destino */
      if ( nodo->contador_claves < (orden-1) )
      {
         /* Comprobamos si es una hoja */
         if ( nodo->hijos[0] == -1 )
         {
            if ( Inserta_Clave_No_Lleno(bdarbol, indice_posible, &nodo, clave)==ERR)
            {
               printf("Error insertando la clave en una pagina no llena\n");
               if ( nodo ) Libera_Pagina(nodo, orden);
               return ERR;
            }
            if (nodo) Libera_Pagina(nodo, orden);
            nodo = NULL;
            
            return OK;
         }
         else if ( nuevo )
         {
            /* Venimos de una promocion, y hay espacio;
               unimos la pagina promocionada a la pagina padre
            */
            padre = NULL;
            if ( Mete_Clave(&nodo,-1, nuevo, 0, NULL, NULL, orden)==ERR)
            {
               printf("Error insertando promocion en pagina con hueco en Inserta_Clave\n");
               return ERR;
            }
            
            if ( BDEscribe_Pagina( bdarbol, nodo, nodo->offset)==ERR)
            {
               printf("Error escribiendo promocion final en Inserta_Clave\n");
               return ERR;
            }
            if ( nodo ) Libera_Pagina(nodo, orden);
            hecho = 1;
         }
         else
         {
            printf("Insercion fuera de hoja en Inserta_Clave\n");
            hecho = 1;
         }
      }
      /* La pagina esta llena, tendremos que redistribuir o promocionar */
      else
      {
         /* Insercion mas alla de la raiz */
         if ( nodo->padre == -1 )
         {
            /* Hemos promocionado hasta la raiz, insertamos y escribimos */
            if ( nuevo )
            {
               /* Insertamos la pagina promocionada antes de partir
               la raiz */
               if ( Mete_Clave(&nodo,-1, nuevo, 0, NULL, NULL, orden+1)==ERR)
               {
                  printf("Error insertando promocion en pagina sin hueco en Inserta_Clave\n");
                  return ERR;
               }   
               /* Ya hemos insertado la clave, no la volvemos a insertar */
               indice_posible = -1;
               orden++;
            }

            memcpy(&posicion, &(bdarbol->pCabecera->sRelleno[4]), 4);
            if ( Partir_Y_Guardar(bdarbol, nodo, &nuevo, indice_posible, orden, clave, posicion, 0)==ERR)
            {
               printf("No funciono Partir_Y_Guardar en Inserta_Clave\n");
               return ERR;
            }
                        
            if ( BDEscribe_Pagina( bdarbol, nuevo, posicion ) == ERR )
            {
               printf("Error escribiendo nueva raiz en Inserta_Clave\n");
               return ERR;
            }
            hecho = 1;
         }
      
         else
         {
            
            /* Obtenemos al padre, para averiguar si hay espacio para redistribuir */
            
            if ( Crea_Pagina(&padre, orden, -1) ==ERR)
            {
               printf("Error creando pagina nueva para el padre en Inserta_Clave\n");
               return ERR;
            }
         
            if ( BDLee_Pagina(bdarbol, padre, nodo->padre)==ERR)
            {
               printf("Error obteniendo al nodo padre en Inserta_Clave\n");
               return ERR;
            }
            
            /* Estamos en una insercion en nodo hoja, intentamos
            redistribuir */
            if ( nodo->hijos[0] == -1 )
            {
               if ( Redistribuir(bdarbol , &padre, &nodo, clave, &indice_posible, &hecho)==OK)
               {
                  
                  continue;
               }
               /* Si habia que insertar en los extremos, redistribuimos con la clave y ya hemos terminado */
               else hecho = 0;
            }
            /* Venimos de una promocion, y donde promocionamos esta lleno */
            if ( nuevo != NULL && nodo->hijos[0] != 1)
            {
               /* Insertamos el promocionado en una pagina de tam orden*/
               orden++;
               if ( Mete_Clave(&nodo,-1, nuevo, 0, NULL, NULL, orden)==ERR)
               {
                  printf("Error insertando promocion en pagina sin hueco en Inserta_Clave\n");
                  return ERR;
               }
               indice_posible = -1;
            }
            else if ( nuevo != NULL )
            {
               printf("Error, no podemos estar promocionando en una hoja\n");
               return ERR;
            }

            if ( Partir_Y_Guardar(bdarbol, nodo, &nuevo, indice_posible, orden,clave, padre->offset,-1) == ERR )
            {
               printf("No funciono Partir_Y_Guardar en Inserta_Clave\n");
               return ERR;
            }
            
            /* Recuperamos el valor de orden ya que puede haber cambiado
            al hacer un partir sobre una tabla orden+1 */
            memcpy(&orden, &(bdarbol->pCabecera->sRelleno[8]),sizeof(int));
            
            /* Borramos nodo para que nos deje un hueco */
            if ( BDBorra_Pagina( bdarbol, nodo->offset, -1)==ERR)
            {
               printf("Error borrando nodo en Inserta_Clave\n");
               return ERR;
            }

                        
            /* Ahora la pagina destino (nodo) es la actual padre */
            if ( nodo ) Libera_Pagina(nodo, orden);
            nodo = padre;
            
            /* Volvemos al bucle para continuar con la promocion */
         }
         
      }
   }   
      
   if ( padre ) Libera_Pagina( padre,orden );
   padre = NULL;
            
   return OK;
}


/****************************************
      Inserta_Clave_No_Lleno
Descripcion:
   Inserta una clave dada en una pagina (no llena) dada
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   indice_posible: indice en el cual poner la clave
   nodo: la pagina en la cual insertar
   *clave: puntero a una clave a insertar previamente creada

Salidas:
   codigo de error
Notas:
   La posicion de la bd debe de ser la misma que desde la lectura de nodo, es decir,
   la del registro siguiente a nodo
   
   Libera la memoria de nodo

****************************************/

int Inserta_Clave_No_Lleno(BDFichero *bdarbol, int indice_posible, PAGINA **nodo, CLAVE *clave)
{
   int orden=0;
   
   
   /* CdE */
   if ( bdarbol == NULL || clave == NULL )
   {
      printf("Error en los parametros de Inserta_Clave\n");
      return ERR;
   }
   
   memcpy(&orden, &(bdarbol->pCabecera->sRelleno[8]),sizeof(int));
   if ( orden < 1 )
   {
      printf("Error en la bd del indice arboreo\n");
      return ERR;
   }
   
   
   if ( Mete_Clave( nodo, indice_posible, NULL, -1, clave, NULL, orden )==ERR)
   {
      printf("Error metiendo clave en Inserta_Clave_No_Lleno\n");
      return ERR;
   }   
   
   /* Guardamos la pagina despues de modificarla */
   if ( BDEscribe_Pagina(bdarbol, (*nodo), (*nodo)->offset)==ERR)
   {
      printf("Error escribiendo la pagina a insertar en Inserta_Clave_No_Lleno\n");
      return ERR;
   }
   

   return OK;
}

/****************************************
      Redistribuir
Descripcion:
   Funcion de redistribucion. Redistribuye los elementos de
   las paginas dst y src segun sea insercion o borrado
   en donde vayamos a insertar a paginas (no llenas) adyacentes
   
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   *padre: puntero al padre desde el cual redistribuir
   offset: offset de la pagina desde la cual se pide la redistribucion
   *clave: Si esta presente, significa que estamos insertando esta clave,
      sino es que se trata de una operacion de borrado

Salidas:
   codigo de error
Notas:
   

****************************************/

int Redistribuir(BDFichero *bdarbol , PAGINA **padre, PAGINA **nodo, CLAVE *clave, int *indice_posible, int *hecho)
{
   int i=0, orden=0, elegido=0,b=0;
   PAGINA *izq=NULL, *der=NULL, *dst=NULL, *src=NULL;
   CLAVE *temp=NULL;
   int posi_clave_en_padre=0, posi_clave_dst=0, posi_clave_src=0,posi_clave_extremo=0;
   /* CdE */
   if ( bdarbol == NULL || padre == NULL || nodo == NULL )
   {
      printf("Parametros erroneos en Redistribuir\n");
      return ERR;
   }
   
   memcpy(&orden, &(bdarbol->pCabecera->sRelleno[8]),4);
   
   if ( Lee_Der_Izq(bdarbol, (*padre), (*nodo)->offset, &der, &izq, &i)==ERR)
   {
      printf("Error leyendo las paginas hermanas\n");
      return ERR;
   }
   
   if ( ( temp = calloc(1, sizeof(CLAVE)))==NULL)
   {
      printf("Error localizando clave temporal en Redistribuir\n");
      return ERR;
   }
   
   if ( Crea_Pagina( &src, orden, -1 ) == ERR )
   {
      printf("Error creando pagina inicializada en Redistribuir\n");
      return ERR;
   }
   if ( Crea_Pagina( &dst, orden, -1 ) == ERR )
   {
      printf("Error creando pagina inicializada en Redistribuir\n");
      return ERR;
   }

   
   if ( izq )
   {
      if ( clave && izq->contador_claves < (orden-1) )
      {
         elegido = 1;
         BDLee_Pagina(bdarbol, dst, izq->offset);
         Libera_Pagina(izq, orden);
         BDLee_Pagina(bdarbol, src, (*nodo)->offset);
         posi_clave_dst = dst->contador_claves;
         posi_clave_extremo = 0;
         posi_clave_en_padre = i-1;
         posi_clave_src = 0;
      
      }
      else if ( clave == NULL && izq->contador_claves > floor(orden/2) )
      {
         elegido = 3;
         BDLee_Pagina(bdarbol, dst, (*nodo)->offset);
         BDLee_Pagina(bdarbol, src, izq->offset);
         Libera_Pagina(izq, orden);
         posi_clave_src = src->contador_claves-1;
         posi_clave_dst = 0;
         posi_clave_extremo = -1;
         posi_clave_en_padre = i-1;
         *indice_posible = -2;
      }
         
      
   }
   if ( der && elegido == 0 )
   {
      if ( clave && der->contador_claves < (orden-1) )
      {
         
         elegido = 2;
         BDLee_Pagina(bdarbol, dst, der->offset);
         BDLee_Pagina(bdarbol, src, (*nodo)->offset);
         Libera_Pagina(der, orden);
         posi_clave_dst = 0;
         posi_clave_extremo = orden-1;
         posi_clave_en_padre = i;
         posi_clave_src = (*nodo)->contador_claves-1;
      }
      else if ( !clave && der->contador_claves > floor(orden/2) )
      {
         elegido = 4;
         BDLee_Pagina(bdarbol, dst, (*nodo)->offset);
         BDLee_Pagina(bdarbol, src, der->offset);
         Libera_Pagina(der, orden);
         posi_clave_src = 0;
         posi_clave_dst = dst->contador_claves;
         posi_clave_extremo = -1;
         posi_clave_en_padre = i;
         *indice_posible = -2;
      }
      else return LLENO;
   }
   if ( elegido == 0 ) return LLENO;
   
   /* Si el indice_posible se tiene que insertar en un extremo, pasamos la  clave al padre para redistribuir */
   if ( *indice_posible == posi_clave_extremo )
   {
      if ( Mete_Clave( padre   , posi_clave_en_padre, NULL, -1, clave, &temp,orden)==ERR)
      {
         printf("Error reemplazando clave en Redistribuir\n");
         return ERR;
      }
      *hecho = 1;
   }
   /* Pasamos el elemento menor de nodo a la posicion de la clave correspondiente en padre */
   else
   {
      if ( Mete_Clave( padre, posi_clave_en_padre, src, posi_clave_src, NULL, &temp,orden)==ERR)
      {
         printf("Error reemplazando clave en Redistribuir\n");
         return ERR;
      }
      /* Estamos redistribuyendo entre paginas padres, redistribuimos los hijos */
      if ( src->hijos[0] != -1 )
      {
         if ( posi_clave_dst == 0 )
         {
            /* Movemos los hijos una posicion a la derecha */
            b = dst->contador_claves+1;
            while ( b>0 )
            {
               if ( dst->hijos[b]==-1 && dst->hijos[b-1] != -1)
               {
                  dst->hijos[b] = dst->hijos[b-1];
                  dst->hijos[b-1] = -1;
               }
               b--;
            }
         }
         if ( posi_clave_dst == 0 )
            dst->hijos[posi_clave_dst] = src->hijos[posi_clave_src+1];
         else   dst->hijos[posi_clave_dst] = src->hijos[posi_clave_src+1];
      }
   
      if ( Elimina_Clave( &src, posi_clave_src, orden)==ERR)
      {
         printf("Error eliminando clave en Redistribuir\n");
         return ERR;
      }
      if ( posi_clave_dst == 0) src->hijos[posi_clave_src+1] = -1;
   
      /* si estamos borrando, guardamos los cambios a la pagina fuente ya */
      if ( clave )
      {
         /* Decrementamos el indice_posible, ya que ahora los elementos se
         han movido una posicion hacia abajo */
         if ( elegido == 1) *indice_posible = *indice_posible - 1;   
         if ( Mete_Clave( &src, *indice_posible, NULL, -1, clave, NULL,orden)==ERR)
         {
            printf("Error insertando clave en Redistribuir\n");
            return ERR;
         }
         *hecho = 1;
      }         
   }
   
   if ( BDEscribe_Pagina(bdarbol, src, src->offset)==ERR)
      {
         printf("Error escribiendo pagina izquierda en Redistribuir_Insercion\n");
         return ERR;
      }
   
   if ( Mete_Clave( &dst, posi_clave_dst, NULL, -1, temp, NULL, orden)==ERR)
   {
      printf("Error insertando clave temporal en pagina destino dentro de Redistribuir_Insercion\n");
      return ERR;
   }
   if ( BDEscribe_Pagina(bdarbol, dst, dst->offset)==ERR)
   {
      printf("Error escribiendo pagina izquierda en Redistribuir_Insercion\n");
      return ERR;
   }
   
   if ( BDEscribe_Pagina(bdarbol, (*padre), (*padre)->offset)==ERR)
   {
      printf("Error escribiendo pagina padre en Redistribuir_Insercion\n");
      return ERR;
   }
   
   
   if ( src ) Libera_Pagina(src,orden);
   if ( dst ) Libera_Pagina(dst,orden);
   if ( temp )
   {
      if ( temp->clave ) free(temp->clave);
      free(temp);
   }
   
   return OK;
}

/****************************************
      Partir_Y_Guardar
Descripcion:
   Realiza la operacion de partir una pagina para promocionar un valor
   y guardar en disco los cambios (estableciendo apropiadamente los offsets
   de los hijos y los numeros de pagina)
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   *clave: cadena de la clave a buscar
   nodo: pagina a usar como fuente de la informacion para partir
   nuevo: pagina donde se dejara el nuevo elemento a insertar
   indice_posible: posicion donde se efectuara la particion
   orden: orden del arbolb
   clave: clave a insertar (si indice_posible > -1)
   offset_padre: offset del padre a pasar a los hijos (izq y der)
   num_pag: numero de pagina a asignar a nuevo   

Salidas:
   codigo de error
Notas:
   

****************************************/
int Partir_Y_Guardar(BDFichero *bdarbol, PAGINA *nodo, PAGINA **nuevo, int indice_posible, int orden, CLAVE *clave, long offset_padre, int num_pag)
{
   PAGINA *izq=NULL, *der=NULL;
   int orden2=0;
   int mas=0;
   /* CdE */
   if ( !bdarbol || !nodo || !nuevo || offset_padre < sizeof(BDCabecera)-1 )
   {
      printf("Error en los parametros de Partir_Y_Guardar\n");
      return ERR;
   }

   if ( indice_posible > -1 && !clave )
   {
      printf("Error en los parametros de Partir_Y_Guardar\n");
      return ERR;
   }

   memcpy(&orden2, &(bdarbol->pCabecera->sRelleno[8]),4);
   if ( orden > orden2 ) mas = 1;
   /* Partimos el nodo actual y promocionamos el valor
   medio */
   if ( Partir( nodo, &der,&izq, nuevo, indice_posible, orden, clave, mas)==ERR)
   {
      printf("Error partiendo en Partir_Y_Guardar\n");
      return ERR;
   }
   
   
   /* der e izq acabaran siendo hijos de nodo al final otra vez */
   der->padre = offset_padre;
   izq->padre = offset_padre;
   
   /* Tenemos que escribir der e izq para que nos den sus offsets y asignarlos en nuevo */
   if ( BDEscribe_Pagina( bdarbol, der, -1 ) == ERR )
   {
      printf("Error escribiendo nuevo hijo de raiz en Partir_Y_Guardar\n");
      return ERR;
   }

   if ( BDEscribe_Pagina( bdarbol, izq, -1 ) == ERR )
   {
      printf("Error escribiendo nuevo hijo de raiz en Partir_Y_Guardar\n");
      return ERR;
   }
   
   
   
   /* Actualizamos todos los hijos de izq y der para cambiarles el padre */
   if ( Actualiza_Hijos(bdarbol, izq, orden2)==ERR)
   {
      printf("Error actualizando el campo padre de los hijos de izq\n");
      return ERR;
   }
   if ( Actualiza_Hijos(bdarbol, der, orden2)==ERR)
   {
      printf("Error actualizando el campo padre de los hijos de der\n");
      return ERR;
   }
         
   
   if ( num_pag < 0) (*nuevo)->padre = offset_padre;
   else (*nuevo)->numero_pag = num_pag;
   
   (*nuevo)->hijos[0] = izq->offset;
   (*nuevo)->hijos[1] = der->offset;

   return OK;
}

/****************************************
      Partir
Descripcion:
   Parte una pagina en dos paginas distintas y crea una nueva donde
   mete la clave dada
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   *clave: cadena de la clave a buscar
   nodo: pagina a usar como fuente de la informacion para partir
   der: pagina donde se guardara la parte derecha (menor) de la particion
   izq: pagina donde se guardara la parte izquierda (mayor) de la particion
   nueva: pagina donde se dejara el nuevo elemento a insertar
   indice: posicion donde se efectuara la particion
   orden: orden del arbolb
   

Salidas:
   codigo de error
Notas:
   

****************************************/
int Partir( PAGINA *nodo, PAGINA **der, PAGINA **izq, PAGINA **nueva, int indice, int orden, CLAVE *clave, int masuno)
{
   int i=0, b=0,c=0;
   /* CdE */
   if ( nodo == NULL || der ==NULL || izq== NULL  || nueva == NULL )
   {
      printf("Error en los parametros de Partir\n");
      return ERR;
   }

   if ( Crea_Pagina( izq, orden-masuno, -1 ) == ERR )
   {
      printf("Error creando pagina inicializada en Partir\n");
      if ( der ) Libera_Pagina((*der),orden);
      return ERR;
   }
   
   /* Copiamos las claves de la izquierda */
   while ( i < floor((orden-1)/2) )
   {
      if ( i == indice )
      {
         if ( Copia_Clave( &((*izq)->claves[i]), clave)==ERR)
         {
            printf("Error copiando clave en Partir\n");
            return ERR;
         }
      }
      else
      {
         if ( Copia_Clave( &((*izq)->claves[i]), nodo->claves[b])==ERR)
         {
            printf("Error copiando clave en Partir\n");
            return ERR;
         }
         b++;
      }   
      (*izq)->hijos[i] = nodo->hijos[i];
      (*izq)->contador_claves++;
      i++;
      
   }
   if ( masuno) (*izq)->hijos[i] = nodo->hijos[i];
   /* Creamos la pagina que sera padre */
   if ( Crea_Pagina( nueva, orden-masuno, -1 ) == ERR )
   {
      printf("Error creando pagina nueva en Partir\n");
      if ( (*izq) ) Libera_Pagina((*izq), orden);
      return ERR;
   }
   
   /* Si el valor medio es la clave nueva, la ponemos en la pagina a promocionar */
   if ( i == indice )
   {
      if ( Copia_Clave( &((*nueva)->claves[0]), clave)==ERR)
      {
         printf("Error copiando clave en Partir\n");
         return ERR;
      }
   }
   else
   {
      if ( Copia_Clave( &((*nueva)->claves[0]), nodo->claves[b])==ERR)
      {
         printf("Error copiando clave en Partir\n");
         return ERR;
      }
      b++;
   }   
   (*nueva)->contador_claves++;
   i++;
   
   if ( Crea_Pagina( der, orden-masuno, -1 ) == ERR )
   {
      printf("Error creando pagina izquierda en Partir\n");
      if ( (*izq) ) Libera_Pagina((*izq), orden);
      if ( (*nueva) ) Libera_Pagina((*nueva), orden);
      return ERR;
   }
      
   c=0;
   /* Copiamos las claves de la derecha */
   while ( i <= nodo->contador_claves )
   {
      if ( masuno == 1 && i == nodo->contador_claves ) break;
      if ( i == indice )
      {
         if ( Copia_Clave( &((*der)->claves[c]), clave)==ERR)
         {
            printf("Error copiando clave en Partir\n");
            return ERR;
         }
      }
      
      else
      {
         if ( Copia_Clave( &((*der)->claves[c]), nodo->claves[b])==ERR)
         {
            printf("Error copiando clave en Partir\n");
            return ERR;
         }
         b++;
      }   
      (*der)->hijos[c] = nodo->hijos[i];
      (*der)->contador_claves++;
      i++;
      c++;
      
   }
   if ( masuno ) (*der)->hijos[c] = nodo->hijos[i];
   
   return OK;
}

/****************************************
      Actualiza_Hijos
Descripcion:
   Actualiza el campo padre de los hijos de la pagina dada
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   padre: el padre desde el que leer los hijos a actualizar
   orden: orden del arbolb

Salidas:
   codigo de error
Notas:
   

****************************************/
int Actualiza_Hijos(BDFichero *bdarbol, PAGINA *padre, int orden)
{
   PAGINA *buf=NULL;
   int i = 0;
   
   if ( Crea_Pagina(&buf, orden,-1)==ERR)
   {
      printf("Error localizando pagina buffer en Partir_Y_Guardar\n");
      return ERR;
   }
   
   for ( i = 0; i < padre->contador_claves+1; i++)
   {
      if( padre->hijos[i] != -1 )
      {
         if ( BDLee_Pagina(bdarbol, buf, padre->hijos[i])==ERR)
         {
            printf("Error leyendo hijo al actualizar padre en Partir_Y_Guardar\n");
            if ( buf ) Libera_Pagina(buf, orden);
            return ERR;
         }
         buf->padre = padre->offset;
         if ( BDEscribe_Pagina(bdarbol, buf, buf->offset)==ERR)
         {
            printf("Error reescribiendo hijos en Partir_Y_Guardar\n");
            if ( buf ) Libera_Pagina(buf, orden);
            return ERR;
         }
      }
   }

   if ( buf ) Libera_Pagina(buf, orden);
   return OK;
}
/****************************************
      Busca_Clave
Descripcion:
   Busca una clave dada en el arbol a partir de la pagina dada (generalmente la raiz, 0).
   Tambien devuelve la posicion en la que se deberia situar la clave en una pagina para
   su insercion.
   
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   **pag: puntero a la pagina previamente localizada en la cual guardar
      la pagina en la que esta (o deberia estar) la clave
   *clave: cadena de la clave a buscar
   pagina: pagina desde la cual empezar a buscar
   offset: offset de la pagina desde la cual empezar a buscar
   indice_posible: entero en el que guardar la posicion que deberia ocupar la
      clave en caso de insercion
   indice_clave: indice de la clave dentro de la pagina en caso de haberla encontrado
   una_pag: si es 1, significa que limitamos la busqueda a la primera pagina

Salidas:
   Escribe en pag el puntero a la estructura de la pagina en la que se encuentre la clave, y modifica
   indice_clave para que contenga la posicion de la clave en el indice (-1 si no esta)
   Codigo de error
Notas:
   Si una_pag es 1 limitamos la busqueda a la primera pagina, en cualquier otro caso
   se ignora
****************************************/

int Busca_Clave ( BDFichero *bdarbol, PAGINA **pag, const void *clave, int pagina, long offset, int *indice_posible, int *indice_clave, int una_pag)
{
   int i=0, orden=0;
   long posicion=0;
   int  (*funcmp) (const void *a, const void *b);
   
   /* Por defecto indicamos que hubo un error buscando la clave o que no se encontro */
   *indice_posible = -1;
   *indice_clave = -1;
   
   /* CdE */
   if ( bdarbol == NULL || clave == NULL || pagina < 0 || indice_posible == NULL || indice_clave == NULL)
   {
      printf("Error en los parametros de Busca_Clave\n");
      *indice_posible = -1;
      *indice_clave = -1;
      return ERR;
   }
   
   memcpy(&orden, &(bdarbol->pCabecera->sRelleno[8]), 4);
   
   /* Leemos la informacion de la pagina desde la cual empezar a buscar, si existe */
   
   /* Obtenemos la posicion de la pagina, leyendo secuencialmente todos los registros
   si no es la raiz -> no es muy bueno */
   if ( pagina > 0 && offset < 0 )
   {
      posicion = Busca_Sec_Pagina(bdarbol, pagina);
   }

   if ( (posicion == -1  || pagina == 0 ) && offset < 0)
   {
      memcpy(&posicion, &(bdarbol->pCabecera->sRelleno[4]), 4);
   
      if ( posicion < 0 )
      {
         printf("Error en la posicion de la raiz de la bd del arbol en Busca_Clave\n");
         *indice_posible = -1;
         *indice_clave = -1;
         return ERR;
      }
   }
   else posicion = offset;
      
   /* No funciona */
   memcpy(&funcmp, &(bdarbol->pCabecera->sRelleno[12]), sizeof(void*));
   
   /* Empezamos en la pagina de la posicion que hayamos encontrado (raiz u otra) */
   while (  posicion != -1 )
   {
      /* Tenemos que borrar y localizar una pagina en cada pagina que analizamos */
      if ( (*pag) ) Libera_Pagina((*pag), orden);
      (*pag) = NULL;
      
      if ( Crea_Pagina(pag, orden, -1) ==ERR)
      {
         printf("Error creando pagina nueva en Busca_Clave\n");
         return ERR;
      }
   
      if ( BDLee_Pagina( bdarbol, (*pag), posicion ) == ERR )
      {
         printf("Error leyendo la pagina en Busca_Clave\n");
         *indice_posible = -1;
         *indice_clave = -1;
         return ERR;
      }
      
      /* Buscamos la clave en la pagina, o la pagina hija en la que deberia estar */
      /* Ponemos condicion de error en la posicion, y indice_posible a 0 por si es un arbol vacio*/
      posicion = -1;
      *indice_posible = 0;
      
      for ( i = 0;i < (*pag)->contador_claves; i++ )
      {
               
         /* Hacemos una comparacion de bytes entre las claves para saber si es igual */
         if ( strncmp(((CLAVE*)(*pag)->claves[i])->clave, clave, ((CLAVE*)(*pag)->claves[i])->tam_clave)==0)
         {
            /* Hemos encontrado la clave, devolvemos la pagina y el indice donde
            se encuentra */
            *indice_clave = i;
            *indice_posible = -1;
            return OK;
         }
         
         else if ( strcmp(((CLAVE*)(*pag)->claves[i])->clave, clave)>0)
         {
            /* Nos vamos al hijo izquierdo (menor) de la clave actual */
            posicion = (*pag)->hijos[i];
            *indice_posible = i;
            /* Como la pagina esta ordenada, y es menor, no tiene sentido
            seguir buscando en esta pagina, acabamos y vamos a la pagina hija si la
            hay */
            i = (*pag)->contador_claves;
         }
         else
         {
            /* A menos que sea menor,vamos al hijo mayor a la clave dada */
            posicion = (*pag)->hijos[i+1];
            *indice_posible = i+1;
         }
         
      }
      if ( una_pag == 1 ) posicion = -1;
      
   }
   
   return OK;
}


/****************************************
      Busca_Sec_Pagina
Descripcion:
   Busca una pagina dada en el arbol, leyendo secuencialmente todas las paginas
   
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   pagina: pagina a encontrar

Salidas:
   La posicion en la bd de la pagina, -1 si no la encuentra
Notas:
   
****************************************/
long Busca_Sec_Pagina(BDFichero *bdarbol, int pagina)
{
   PAGINA *pag=NULL;
   int tamano=0, orden=0;
   long posicion=-1;
   int i=0;
   
   /* CdE */
   if ( bdarbol == NULL || pagina < 0 )
   {
      printf("Error en los parametros de Busca_Sec_Pagina\n");
      return ERR;
   }
   
   
   posicion = sizeof ( BDCabecera ) - 1;
   /* Buscar secuencialmente la pagina en la bd */
   memcpy(&tamano, bdarbol->pCabecera->sRelleno, 4);
   memcpy(&orden, &(bdarbol->pCabecera->sRelleno[8]),4);
   
   while ( i != ERR )
   {
      
      if ( Crea_Pagina( &pag, orden, -1) == ERR  )
      {
         printf("Error creando pagina en Busca_Sec_Pagina\n");
         return -1;
      }

      i = BDLee_Pagina( bdarbol, pag, posicion );
      if ( i != ERR && i != VACIO )
      {
         if ( pag->numero_pag == pagina )
            i = ERR;
         else posicion += tamano;
      }
      /* La pagina pedida no estaba presente */
      else posicion=-1;
      
      if ( pag ) Libera_Pagina(pag, orden);
      pag = NULL;
   
   }
   return posicion;
}

/****************************************
      Borra_Clave
Descripcion:
   Borra una clave dada del  arbolb y de la bd
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   *clave: puntero a una clave a eliminar previamente creada

Salidas:
   codigo de error
Notas:
   

****************************************/

int Borra_Clave( BDFichero *bdarbol, BDFichero *origen, void *clave)
{
   int orden=0, indice_posible=0, indice_clave=0;
   int estado=0;
   long posicion_registro_original=0;
   PAGINA *nuevo=NULL, *padre=NULL;
   CLAVE *foo=NULL;

   /* CdE */
   if ( bdarbol == NULL || clave == NULL )
   {
      printf("Error en los parametros de Borra_Clave\n");
      return ERR;
   }
   
   memcpy(&orden, &(bdarbol->pCabecera->sRelleno[8]),sizeof(int));
   if ( orden < 1 )
   {
      printf("Error en la bd del indice arboreo\n");
      return ERR;
   }
   
   /* Buscamos la clave en el arbol */
   if ( Busca_Clave(bdarbol, &padre, clave, 0, -1, &indice_posible, &indice_clave,0)== ERR )
   {
      printf("Error buscando clave en el arbol en Borra_Clave\n");
      return ERR;
   }
   else if ( indice_clave == -1 )
   {
      printf("Clave no encontrada en el arbol en Borra_Clave\n");
      if ( padre ) Libera_Pagina(padre, orden);
      return ERR;
   }
   
   posicion_registro_original = (padre->claves[indice_clave])->offset;
   /* La clave esta en un nodo padre, tenemos que buscar su elemento inmediatamente
   mayor para intercambiarlo por el y luego borrarlo */
   if ( padre->hijos[0] != -1 )
   {
      if ( Buscar_Clave_Adyacente( bdarbol, padre, &nuevo, indice_clave)==ERR)
      {
         printf("Error buscando la clave adyacente en Borra_Clave\n");
         return ERR;
      }
      /* Metemos el primer elemento de la pagina con el sucesor en nodo */
      if ( Mete_Clave( &padre, indice_clave, nuevo, 0, NULL, &foo, orden)==ERR)
      {
         printf("Error pasando la clave adyacente a padre en Borra_Clave\n");
         return ERR;
      }
      
      if ( Elimina_Clave( &nuevo, 0, orden )==ERR)
      {
         printf("Error borrando clave de la pagina hoja\n");
         return ERR;
      }
      
      /* Guardamos la modificacion a nuevo */
      if ( BDEscribe_Pagina(bdarbol, nuevo, nuevo->offset)==ERR)
      {
         printf("Error guardando el intercambio en padre en Borra_Clave\n");
         return ERR;
      }
   }
   else if ( padre->hijos[0] == -1 )
   {
      if ( Elimina_Clave( &padre, indice_clave, orden)==ERR)
      {
         printf("Error borrando clave de la pagina hoja\n");
         return ERR;
      }
   }
   else
   {
      printf("Error, intento de borrar en pagina padre\n");
      return ERR;
   }
   

   /* Escribimos la eliminacion de la clave antes de averiguar si la pagina ha quedado
   valida o no */
   if ( BDEscribe_Pagina(bdarbol, padre, padre->offset)==ERR)
   {
      printf("Error guardando pagina borrada\n");
      return ERR;
   }   

   /* Hemos borrado en una pagina hoja, leemos la pagina actual en nuevo
   y liberamos padre para leer el padre de nuevo alli */
   if ( !nuevo )
   {
      if ( Crea_Pagina(&nuevo, orden, -1 ) == ERR )
      {
         printf("Error creando pagina nueva en Borra_Clave\n");
         return ERR;
      }
      
      if ( BDLee_Pagina(bdarbol, nuevo, padre->offset)==ERR)
      {
         printf("Error copiando la pagina actual en nuevo\n");
         return ERR;
      }
   }
   
   /* Solo leemos el padre en caso de que no estemos borrando en la raiz */
   if ( nuevo->padre != -1)
   {
      /* Ahora nuevo es el actual padre y padre pasa a ser el padre de nuevo */
      if ( BDLee_Pagina(bdarbol, padre, nuevo->padre)==ERR)
      {
         printf("Error leyendo el padre de la pagina hoja utilizada en Borra_Clave\n");
         return ERR;
      }
   }

   /* No hay suficientes elementos restantes en la pagina para satisfacer la
   condicion de pagina de arbolb: tenemos que (1) redistribuir o (2) concatenar
   lo que quede de la pagina actual y la clave padre de la borrada en una pagina
   lateral a la que contenia la clave borrada */
   if ( nuevo->contador_claves < floor(orden/2) && nuevo->padre != -1)
   {
      if ( Fundir( bdarbol, &padre, &nuevo )==ERR)
      {
         printf("Hubo un error fundiendo paginas\n");
         return ERR;
      }

      
   }
   else if ( padre->padre == -1 && padre->contador_claves == 0)
   {
      /* Borramos la raiz, ya que esta vacia */
      bdarbol->lPosicionActual = padre->offset;
      if ( BDBorraRegistro(bdarbol)==ERR)
      {
         printf("Error borrando la raiz en Borra_Clave\n");
         return ERR;
      }
      
      /* Cuando se inserte una pagina otra vez, ira a lPosicionBorrado, luego la
      raiz estara alli */
      estado = bdarbol->pCabecera->lPosicionBorrado;
      memcpy(&(bdarbol->pCabecera->sRelleno[4]), &estado, 4);
   }
   
   /* No borramos el registro de la bd original hasta que hayamos hecho con exito las operaciones
   en el arbolb */
   if ( BDPonte(origen, posicion_registro_original, 0)==ERR)
   {
      printf("Registro inexistente en bd original\n");
      return ERR;
   }
   
   if ( BDBorraRegistro(origen)==ERR)
   {
      printf("Error borrando registro en Borra_Clave\n");
      return ERR;
   }
   return OK;
}

/****************************************
      Fundir
Descripcion:
   Funde dos paginas hijas de un padre y comprueba que el padre
   cumpla la condicion de numero de claves. Repite la operacion
   si el padre no cumple la condicion (a menos que sea raiz).
   
Entradas:
   *bdarbol: puntero a una bd de un arbol binario
   *padre: padre desde el cual empezamos
   *nuevo: hijos del padre desde el cual empezamos
   
Salidas:
   codigo





Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.