#include "StdAfx.h"
#include "DijkstraUtiles.h"
#include "dir_manager.h"
#include "StrArray.h"
#include "..\Olivia\Olivia\olv_tasks_def.h"
/**
*	@file olv_geom.h
*	Archivo de definiciones de clase de varias utilidades geométricas del programa Olivia.
*/

//*************************************************************************************
//Funciones de las estructuras Dijkstra
/**
 * Función para la estructura del algoritmo Dijkstra, para iniciar el nodo
 */
void Djkt_nodo::inicia()
{
	dis = (float)MAYUSCULO;
	id_padre = -1;
	visto = FALSE;
	ids_ady.nady=-1;
	ids_ady.angs=NULL;
	ids_ady.i_conjs=NULL;
	ids_ady.ids_padre=NULL;
};
//*************************************************************************************
BOOL Djkt_nodo::inicia_ex( Djkt_ang_ady *ang )
{
	inicia();

	ids_ady=*ang;
	ids_ady.angs=NULL;

	if(!ids_ady.inicia_ids())
		return FALSE;

	
	return TRUE;
};
//*************************************************************************************
void Djkt_nodo::libera( )
{
	ids_ady.libera_ex();
};
//*************************************************************************************
/**
 * Función para la estructura del algoritmo Dijkstra, para iniciar la cola
 */
void Djkt_cola::inicia(Djkt_nodo *n)
{
	elem = NULL;
	nodos = n;
	nn=0;
};
//*************************************************************************************
/**
 * Función para la estructura del algoritmo Dijkstra, para poner en la cola
 */
BOOL Djkt_cola::pon(int i)
{
	return pon(i,-1);
};
//*************************************************************************************
/**
 * Función para la estructura del algoritmo Dijkstra, para poner en la cola
 */
BOOL Djkt_cola::pon(int i,int i_inci)
{
	int nv=200;
	Djkt_elem_cola *aux = new Djkt_elem_cola();
	Djkt_elem_cola *aux1 = elem;
	Djkt_elem_cola *aux2=NULL;
	while(!aux && nv>0)
	{

		nv--;
		Sleep(1);
		aux = new Djkt_elem_cola();
	}
	if(!aux)
		return FALSE;
	nn++;
	aux->id = i;
	aux->id_inci=i_inci;
	aux->sig = NULL;
	while (true)
	{
		if (!aux1)
		{
			elem = aux;
			break;
		}
		if (nodos[aux1->id].dis >= nodos[aux->id].dis)
		{
			aux->sig = aux1;
			if(aux2)
				aux2->sig=aux;
			if (aux1 == elem)
				elem = aux;
			break;
		}
		if (!aux1->sig)
		{
			aux1->sig = aux;
			break;
		}
		aux2=aux1;
		aux1 = aux1->sig;
	}
	return TRUE;
};
//*************************************************************************************
/**
 * Función para la estructura del algoritmo Dijkstra, para obtener de la cola
 */
int Djkt_cola::dame()
{
	return dame(NULL);
};
//*************************************************************************************
/**
 * Función para la estructura del algoritmo Dijkstra, para obtener de la cola
 */
int Djkt_cola::dame(int *id_inci)
{
	if (!elem)
		return -1;
	if(nn<=0)
	{
		elem=NULL;
		return -1;
	}
	nn--;
	Djkt_elem_cola *aux = elem;
	int res = aux->id;
	elem = elem->sig;
	if(id_inci)
		*id_inci=aux->id_inci;
	delete(aux);
	return res;
};
//*************************************************************************************
/**
 * Función constructor para la estructura de nodos adyacentes para los ángulos
 */
Djkt_ang_ady::Djkt_ang_ady()
{
	nady=0;
	i_conjs=0;
	angs=0;
	ids_padre=NULL;
}
//*************************************************************************************
/**
 * Función destructor para la estructura de nodos adyacentes para los ángulos
 */
void Djkt_ang_ady::libera()
{
	if(i_conjs)
		free(i_conjs);
	i_conjs=NULL;
	if(angs)
	{
		for(int i=0;i<nady;i++)
		{
			if(angs[i])
				free(angs[i]);
			angs[i]=NULL;
		}
		free(angs);
	}
	angs=NULL;
	if(ids_padre)
		free(ids_padre);
	ids_padre=NULL;
}
//*************************************************************************************
/**
 * Función destructor para la estructura de nodos adyacentes para los ángulos
 */
void Djkt_ang_ady::libera_ex()
{
	i_conjs=NULL;
	if(angs)
	{
		for(int i=0;i<nady;i++)
		{
			if(angs[i])
				free(angs[i]);
			angs[i]=NULL;
		}
		free(angs);
	}
	angs=NULL;
	if(ids_padre)
		free(ids_padre);
	ids_padre=NULL;
}
//*************************************************************************************
/**
 * Función de inicio de variables para la estructura de nodos adyacentes para los ángulos
 */
BOOL Djkt_ang_ady::inicia(int n, BOOL no_angs)
{
	int i;
	nady=n;
	if(nady>16)
	{
		nady=nady;
	}
	//malloc
	i_conjs=(int*)malloc(nady*sizeof(int));
	if(!i_conjs)
		return FALSE;
	for(i=0;i<nady;i++)
	{
		i_conjs[i]=-1;
	}
	if(no_angs)
	{
		angs=NULL;
		return TRUE;
	}
	angs=(BYTE**)malloc(nady*sizeof(BYTE*));
	if(!angs)
		return FALSE;
	for(i=0;i<nady;i++)
	{
		angs[i]=(BYTE*)malloc(nady*sizeof(BYTE));
		if(!angs[i])
			return FALSE;
		memset(angs[i],0,nady*sizeof(BYTE));
	}
	return TRUE;
}
//*************************************************************************************
/**
 * Función de inicio de variables para la estructura de nodos adyacentes para los ángulos
 */
BOOL Djkt_ang_ady::inicia_ids()
{
	ids_padre=(Djkt_ids_pdr*)malloc(nady*sizeof(Djkt_ids_pdr));
	if(!ids_padre)
		return FALSE;
	for(int i=0;i<nady;i++)
	{
		ids_padre[i].id=-1;
		ids_padre[i].dis=(float)MAYUSCULO;
	}
	return TRUE;

};		
//*************************************************************************************
/**
 * Para la estructura de nodos adyacentes para los ángulos,
 * devuelve las posiciones relativas a la conjunción de las
 * conjunciones i y j, tanto si tienen que añadirse o buscarse
 */
BOOL Djkt_ang_ady::dame_ii_jj(int i, int j, int *ii_,int *jj_)
{		
	int ii,jj;

	*ii_=-1;
	if(jj_)
		*jj_=-1;
	ii=jj=-1;

	for(ii=0;ii<nady;ii++)
		if((i_conjs[ii]==-1) || (i_conjs[ii]==i))
			break;
	if(i==j)
		jj=ii;
	else if(j!=-1)
	{	
		for(jj=0;jj<nady;jj++)
			if(((jj>ii) && (i_conjs[jj]==-1)) || (i_conjs[jj]==j))
				break;
	}
	if(ii>=nady || jj>=nady)
		return FALSE;

	*ii_=ii;
	if(jj_)
		*jj_=jj;

	return TRUE;
}
//*************************************************************************************
/**
 * Para la estructura de nodos adyacentes para los ángulos,
 * pone el ángulo de la conj, entre las adyacentes i y j
 */
BOOL Djkt_ang_ady::pon_ang_i_j(int i,int j, BYTE ang)
{
	int ii,jj;

	if(!dame_ii_jj(i,j,&ii,&jj))
		return FALSE;

	i_conjs[ii]=i;
	i_conjs[jj]=j;
	angs[ii][jj]=ang;

	return TRUE;
};
//*************************************************************************************
/**
 * Para la estructura de nodos adyacentes para los ángulos,
 * devuelve el ángulo de la conj, entre las adyacentes i y j
 */
BOOL Djkt_ang_ady::dame_ang_i_j(int i,int j, BYTE *ang, BOOL inds_abs)
{
	int ii,jj;

	if(inds_abs)
	{	
		if(!dame_ii_jj(i,j,&ii,&jj))
			return FALSE;
	}
	else
	{
		ii=i;
		jj=j;
	}

	*ang=angs[ii][jj];
	return TRUE;
}
//*************************************************************************************
/**
 * Para la estructura de nodos adyacentes para los ángulos,
 * pone que para llegar al nodo actual desde i_orig, el padre es j_padre
 */
BOOL Djkt_ang_ady::pon_padre(int i_orig,int j_padre, double dis, BOOL inds_abs)
{
	int ii,jj;

	if(inds_abs)
	{	
		if(!dame_ii_jj(i_orig,j_padre,&ii,&jj))
			return FALSE;
	}
	else
	{
		ii=i_orig;
		jj=j_padre;
	}

	ids_padre[ii].id=jj;
	ids_padre[ii].dis=(float)dis;

	return TRUE;
};
//*************************************************************************************
/**
 * Para la estructura de nodos adyacentes para los ángulos,
 * devuelve que el padre es j_padre para ir al nodo actual desde i_orig
 */
BOOL Djkt_ang_ady::dame_padre(int i_orig,int *j_padre, double *dis, BOOL inds_abs)
{
	int ii,jj;

	if(inds_abs)
	{	
		if(!dame_ii_jj(i_orig,-1,&ii,&jj))
			return FALSE;
	}
	else
	{
		ii=i_orig;
		jj=-1;
	}

	*j_padre = i_conjs[ids_padre[ii].id];
	*dis = ids_padre[ii].dis;

	return TRUE;
};
//*************************************************************************************
/*
 * Guarda a disco
 */
BOOL Djkt_ang_ady::guarda(HeadCostAng hd, int ic, char *path , char *ext)
{
	HANDLE hfile = INVALID_HANDLE_VALUE;
	int nb, i;
	char file[MAX_PATH];

	sprintf_s(file,MAX_PATH,"%s%06d.%s",path,ic,ext);

	//crea archivo-----------------------------------
	hfile = CreateFile(file,  GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		i=GetLastError();
		return FALSE;
	}

	//graba cabecera------------		
	nb = sizeof(hd);
	//calcula el nb
	hd.n=nady; //* BYTE
	if (nb != _lwrite((int)hfile, (LPCCH)&hd, nb))
	{
		goto va_mal;
	}
	
	//guarda la matriz de conjs ady
	nb=sizeof(int)*nady;
	if (nb != _lwrite((int)hfile, (LPCCH) i_conjs, nb))
	{
		goto va_mal;
	}
	//guarda la matriz de ángulos
	nb=nady;
	for(i=0;i<nady;i++)
	{	
		if (nb != _lwrite((int)hfile, (LPCCH) angs[i], nb))
		{
			break;
		}	
	}
	if(i<nady)
		goto va_mal;

	CloseHandle(hfile);
	return TRUE;

va_mal:
	CloseHandle(hfile);
	return FALSE;
}
//*************************************************************************************
/*
 * Lee de disco
 */
BOOL Djkt_ang_ady::lee(int ic, char *path , char *ext)
{
	HANDLE hfile = INVALID_HANDLE_VALUE;
	int nb, i;
	char file[MAX_PATH];
	HeadCostAng hd;

	sprintf_s(file,MAX_PATH,"%s%06d.%s",path,ic,ext);

	//crea archivo-----------------------------------
	hfile = CreateFile(file,  GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		i=GetLastError();
		return FALSE;
	}

	//lee cabecera------------	
	memset(&hd,0,sizeof(HeadCostAng));
	nb = sizeof(hd);
	if (nb != _lread((int)hfile,&hd, nb))
	{
		goto va_mal;
	}
	//calcula el nady
	nady=hd.n;	
	
	//lee la matriz de conjs ady, pidiendo memoria antes
	nb=sizeof(int)*nady;
	i_conjs=(int*)malloc(nb);
	if(!i_conjs)
		goto va_mal;
	if (nb != _lread((int)hfile,  i_conjs, nb))
	{
		goto va_mal;
	}

	angs=(BYTE**)malloc(nady*sizeof(BYTE*));
	if(!angs)
		goto va_mal;
	nb=nady;
	for(i=0;i<nady;i++)
	{
		angs[i]=(BYTE*)malloc(nady*sizeof(BYTE));
		if(!angs[i])
			break;
		if (nb != _lread((int)hfile,  angs[i], nb))
			break;
	}
	if(i<nady)
		goto va_mal;

	CloseHandle(hfile);
	return TRUE;

va_mal:
	CloseHandle(hfile);
	return FALSE;
}
//*************************************************************************************
/**
 * Algoritmo Dijkstra de cálculo de camino de menor coste para ir de los 'n' nodos de una red al nodo 'fin'.
 * 'nodos' es el array de tamaño n que contiene la información de costes, es de salida
 * 'costes' es la matriz de nxn que contiene los costes de ir de todos a todos los nodos
 */
BOOL DijkstraUtiles::dijkstra_ang_inv_ok(CmapMatFloat &costes, Djkt_ang_ady *angs, int nn, int fin, Djkt_nodo **nodos, FlagsArray *visto_ang_)
{
	int i, sig,sigr;
	__int64 n = nn;
	Djkt_cola q;
	BOOL res=FALSE;
	Djkt_nodo *distancias;
	double d;
	BOOL ang_ok;
	//BYTE ang;
	int id_inci;
	FlagsArray buffer;
	FlagsArray *visto_ang=NULL;
	int ii,jj;

	q.inicia(NULL);
	distancias = *nodos;
	if(!distancias)
		distancias = (Djkt_nodo*)malloc(size_t(sizeof(Djkt_nodo)*n));
	if (!distancias)
		goto va_mal;
	if(visto_ang_)
		visto_ang=visto_ang_;
	if(!visto_ang)
	{
		//visto_ang = (BYTE*)malloc(n*n*sizeof(BYTE));
		visto_ang = &buffer;
	}
	if(!visto_ang->dimensiona(((__int64)n)*n))
		goto va_mal;
	visto_ang->setAll(FALSE);
	
	if(angs)
	{
		ang_ok=TRUE;
		for (i=0; i<n; i++)
		{			
			if(!distancias[i].inicia_ex(&angs[i]))
				ang_ok=FALSE;			
		}
		
		if(!ang_ok)
			goto va_mal;
		for(i=0; i<distancias[fin].ids_ady.nady; i++)
		{
			distancias[fin].ids_ady.ids_padre[i].dis=0;
			distancias[fin].ids_ady.ids_padre[i].id=-1;
		}
	}
	else
	{
		for (i=0; i<n; i++)
		{
			distancias[i].inicia();
		}
	}
	distancias[fin].id_padre = -1;
	distancias[fin].dis = 0;
	q.inicia(distancias);
	if (!q.pon(fin,fin))
		goto va_mal;

	int j=1;
	while (TRUE)
	{
		sig = q.dame(&id_inci);
		if(sig<0)
			break;//terminado
		if ((*visto_ang)[((__int64)id_inci)*n+sig])
			continue;
		visto_ang->set(((__int64)id_inci)*n+sig,TRUE);
		//se revisa cada nodo 
		for (i = 0; i < n; i++)
		{
			if (costes[i][sig] >= MAYUSCULO)
				continue;	
			if ((*visto_ang)[((__int64)sig)*n+i])//si visto se pasa de el
				continue;
			if(angs)
			{	
				if(!angs[sig].dame_ii_jj(i,-1,&ii,NULL))
					continue;

				if(distancias[sig].ids_ady.ids_padre[ii].id!=-1)
				{								
					if(!angs[sig].dame_ii_jj(distancias[sig].ids_ady.ids_padre[ii].id,-1,&jj,NULL))
						continue;

					if(!angs[sig].angs[ii][jj])
						continue;

				}
				d=distancias[sig].ids_ady.ids_padre[ii].dis + costes[i][sig];

				if (distancias[i].dis > d)//se actualiza distancia si procede
				{
					if(d<0)
						d=d;
					distancias[i].dis = (float)d;
					distancias[i].id_padre = sig;
					visto_ang->set(((__int64)sig)*n+i,0);
					if (!q.pon(i,sig))
						goto va_mal;
				}

				if(!angs[i].dame_ii_jj(sig,-1,&sigr,NULL))
					continue;

				for(jj=0;jj<distancias[i].ids_ady.nady;jj++)
				{
					if((jj==sigr) && (distancias[i].ids_ady.nady>1))
						continue;
					if(!angs[i].angs[jj][sigr])
						continue;

					if (distancias[i].ids_ady.ids_padre[jj].dis > d)//se actualiza distancia si procede
					{
						distancias[i].ids_ady.ids_padre[jj].dis = (float)d;
						distancias[i].ids_ady.ids_padre[jj].id = sig;
						visto_ang->set(((__int64)sig)*n+i,0);
						if (!q.pon(i,sig))
							goto va_mal;
					}
				}	
			}
			else
			{
				//encontrado adyacente se hace la relajacion----------------
				d = distancias[sig].dis + costes[i][sig];
				if (distancias[i].dis > d)//se actualiza distancia si procede
				{
					distancias[i].dis = (float)d;
					distancias[i].id_padre = sig;
					if (!q.pon(i,sig))
						goto va_mal;
				}
			}
			
			
		}
	}
	res = TRUE;
	
	if (nodos)
	{
		*nodos = distancias;
		distancias = NULL;
	}
	
va_mal:
	if (distancias)
		free(distancias);
	while (q.dame() >= 0);

	return res;
}
//*************************************************************************************
/*
 * Da la ruta hasta el nodo final con el que se hizo dijkstra desde 'id_ini'
 * Hay que haber llamado antes a dijkstra, y el array 'nodos' de salida es el que aquí
 * es entrada, de tamaño 1xn.
 * En 'secu' devuelve un array de la secuencia a seguir desde el nodo 'id_ini' hasta el nodo final
 * Es de tamaño el número de nodos de la red, pero sólo están ocupados los 'n' primeros con la secuencia.
 */
double DijkstraUtiles::ruta_dj_inv(int id_ini, int *secu, Djkt_nodo *nodos, int nmax, int *n)
{
	int padre= id_ini;
	int nn = 0;
	while (padre>=0 && nn<nmax)
	{
		secu[nn++] = padre;
		padre = nodos[padre].id_padre;
	}
	if(nn==nmax)
		nn=nn;
	*n = nn;
	
	return nodos[id_ini].dis;
}
//*************************************************************************************
/*
 * Da la ruta hasta el nodo final con el que se hizo dijkstra desde 'id_ini'
 * Hay que haber llamado antes a dijkstra, y el array 'nodos' de salida es el que aquí
 * es entrada, de tamaño 1xn.
 * En 'secu' devuelve un array de la secuencia a seguir desde el nodo 'id_ini' hasta el nodo final
 * Es de tamaño el número de nodos de la red, pero sólo están ocupados los 'n' primeros con la secuencia.
 */
double DijkstraUtiles::ruta_dj_inv_ok(int id_ini, int *secu, Djkt_nodo *nodos, int nmax, int *n)
{
	int padre= id_ini;
	int nn = 0;
	int proce=-1;
	int i;
	if(nodos[padre].ids_ady.nady<=0)
		return ruta_dj_inv(id_ini,secu,nodos,nmax,n);
	while (padre>=0 && nn<nmax)
	{
		
		if(proce<0)
		{
			secu[nn++] = padre;
			proce=padre;
			padre = nodos[padre].id_padre;
			
		}
		else
		{
			secu[nn++] = padre;
			
			if(!nodos[padre].ids_ady.dame_ii_jj(proce,-1,&i,NULL)|| i<0)
			{
				*n = nn;
				return MAYUSCULO;
			}
			proce=padre;
			padre=nodos[padre].ids_ady.ids_padre[i].id;
		}
		
	}
	if(nn==nmax)
		nn=nn;
	*n = nn;
	
	return nodos[id_ini].dis;
}
//*************************************************************************************
Cdijkstra_arch::Cdijkstra_arch()
{
	memset(&hd, 0, sizeof(hd));
	path[0]=0;
	strcpy(extension,EXT_ARCH_DIJ_DEFAULT);
	dis=NULL;
	ia=NULL;
	salta_ids_padres=FALSE;
}
//*************************************************************************************
Cdijkstra_arch::~Cdijkstra_arch()
{
	if(dis)
		free(dis);
}
//*************************************************************************************
BOOL Cdijkstra_arch::inicia( char* path_arch, BOOL nuevo/*=FALSE*/,BOOL borra, int n_nod/*=0*/, int max_conex)
{
	strcpy_s(path,MAX_PATH, path_arch);
	char st[1024];
	salta_ids_padres=FALSE;
	if(nuevo)
	{
		hd.version=VERSION_DJ_ARCHI;
		hd.nn=n_nod;
		hd.nb=0;

		hd.max_conex=max_conex;
		sizn=sizeof(Djkt_nodo)+hd.max_conex*(sizeof(Djkt_ids_pdr)+sizeof(int)+sizeof(BYTE)*hd.max_conex);
		//borra archivos ndj--------------------------------------
		//pilla archivos-----------------
		if(borra)
		{
			StrArray lfiles;
			char *f;
			if(Cdir_manager::listar(st, &lfiles ))
				for (int i = 0; i<lfiles.size(); i++)
				{
					f=lfiles.get((i));
					if(!strcmp(Cdir_manager::extension_archivo(f),extension))
						DeleteFile(f);
				}
				lfiles.borra();		
		}
		
		return hd.nn>0;
	}
	HANDLE hfile = INVALID_HANDLE_VALUE;
	int nb;
	char p[MAX_PATH];
	sprintf_s(p,MAX_PATH, "%s_%ld.%s",path, 0,extension);
	hfile = CreateFile(p,  GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (hfile == INVALID_HANDLE_VALUE)
		return FALSE;
	nb = sizeof(hd);
	if (nb != _lread((int)hfile,&hd, nb))
	{
		goto va_mal;
	}
	if(hfile != INVALID_HANDLE_VALUE)
		CloseHandle(hfile);
	sizn=sizeof(Djkt_nodo)+hd.max_conex*(sizeof(Djkt_ids_pdr)+sizeof(int)+sizeof(BYTE)*hd.max_conex);
	return (hd.version== VERSION_DJ_ARCHI &&  hd.max_conex>0 && hd.nn>0 && sizn>0);

va_mal:
	if(hfile != INVALID_HANDLE_VALUE)
		CloseHandle(hfile);
	return FALSE;
		

}
//*************************************************************************************
BOOL Cdijkstra_arch::add_b( Djkt_nodo* blq, int iref, int inod, BOOL pon_inf )
{
	HANDLE hfile = INVALID_HANDLE_VALUE;
	int nb, i, nbt, j;
	char p[MAX_PATH];
	sprintf_s(p,MAX_PATH,"%s_%ld.%s",path,iref,extension);
	Head_dj_arch hdl;
	//abre archivo-----------------------------------
	hfile = CreateFile(p,  GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		hfile = CreateFile(p,  GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);

		
		if (hfile == INVALID_HANDLE_VALUE)
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error no se puede abrir archivo: %s", p);

			i=GetLastError();
			return FALSE;
		}
		//graba cabecera------------
		hdl=hd;
		hdl.nb=0;
		nb =  sizeof(hdl);
		if (nb != _lwrite((int)hfile, (LPCCH)&hdl, nb))
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error no se puede grabar cabecera  de archivo: %s", p);
			goto va_mal;
		}
	}
	else
	{
		//lee cabecera-------------
		nb =  sizeof(hdl);
		if (nb != _lread((int)hfile, &hdl, nb))
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error no se puede leer cabecera de archivo: %s", p);

			goto va_mal;
		}
	}
	//va a lo ultimo---------------------------------
	if ( SetFilePointer(hfile, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
	{
		//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error no se puede ir al final del archivo: %s", p);

		goto va_mal;
	}
	//guarda bloque---------------------------------
	for (i=0; i<hdl.nn; i++)
	{
		nbt=0;
		//guarda nodo------------------------
		nb =  sizeof(Djkt_nodo);
		if (nb != _lwrite((int)hfile, (LPCCH)&blq[i], nb))
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error al escribir nodo, archivo: %s", p);

			goto va_mal;
		}
		nbt+=nb;		

		if(!blq[i].ids_ady.ids_padre || salta_ids_padres)
		{
			blq[i].ids_ady.nady=0;
			salta_ids_padres=TRUE;
			goto guarda_bas;
		}
		nb=blq[i].ids_ady.nady*sizeof(Djkt_ids_pdr);
		if (nb != _lwrite((int)hfile, (LPCCH)blq[i].ids_ady.ids_padre, nb))
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error al escribir idpadres, archivo: %s", p);

			goto va_mal;
		}
		nbt+=nb;
		nb=blq[i].ids_ady.nady*sizeof(int);
		if (nb != _lwrite((int)hfile, (LPCCH)blq[i].ids_ady.i_conjs, nb))
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error al escribir i_conjs, archivo: %s", p);

			goto va_mal;
		}
		nbt+=nb;
		
		if(blq[i].ids_ady.angs)
		{
			nb=blq[i].ids_ady.nady*sizeof(BYTE);
			for(j=0; j<blq[i].ids_ady.nady; j++)
			{
				
				if (nb != _lwrite((int)hfile, (LPCCH)blq[i].ids_ady.angs[j], nb))
				{
					//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error al escribir angs, archivo: %s", p);

					goto va_mal;
				}
				nbt+=nb;
			}
		}
guarda_bas:
		//guarda basura resto de bytes que quedan libres-------------
		while(nbt<sizn)
		{
			nb=min((sizn-nbt),(int)((sizeof(Djkt_nodo)*hd.nn)));
			if (nb != _lwrite((int)hfile, (LPCCH)blq, nb))
			{
				//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error al escribir relleno, archivo: %s", p);

				goto va_mal;
			}
			nbt+=nb;
		}
	}
	inod=hdl.nb++;
	//graba cabecera------------------------------------
	if ( SetFilePointer(hfile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
	{
		//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error ir a inicio, archivo: %s", p);

		goto va_mal;
	}
	nb=sizeof(Head_dj_arch);
	if (nb != _lwrite((int)hfile, (LPCCH)&hdl, nb))
	{
		//wgeotext(LOG_TODO,"Cdijkstra_arch::add_b","Error al escrivir cabecera, archivo: %s", p);

		goto va_mal;
	}
	CloseHandle(hfile);
	if(pon_inf)
	{
#ifdef DEBUG
			if (!AfxCheckMemory())
				C_log::log("Cdijkstra_arch","Error memoria");
#endif 

		pon_info_amb(blq, iref, inod);

#ifdef DEBUG
			if (!AfxCheckMemory())
				C_log::log("Cdijkstra_arch","Error memoria");

#endif 
	}


	return TRUE;
	

va_mal:
	if(hfile != INVALID_HANDLE_VALUE)
		CloseHandle(hfile);
	return FALSE;
}
//*************************************************************************************
void Cdijkstra_arch::libera_buf(Djkt_nodo* buf )
{
	if(!buf)
		return;
	for (int i=0; i<hd.nn; i++)
	{
		buf[i].ids_ady.libera();
	}
	free(buf);
}
//*************************************************************************************
Djkt_nodo* Cdijkstra_arch::dame_buf_nodos(BOOL angulos )
{
	Djkt_nodo*buf_res=(Djkt_nodo*)malloc(sizeof(Djkt_nodo)*hd.nn);
	if(!buf_res)
	{
		return buf_res;
	}
	memset(buf_res,0, sizeof(Djkt_nodo)*hd.nn);
	for (int i=0; i<hd.nn; i++)
	{
		if(!buf_res[i].ids_ady.inicia(hd.max_conex, !angulos)||!buf_res[i].ids_ady.inicia_ids())
		{
			for (int ii=0; ii<=i; ii++)
			{
				buf_res[ii].ids_ady.libera();
				free(buf_res);
				return NULL;
			}
		}
	}


	return buf_res;
}
//*************************************************************************************
//por ahora hecha solo pidiendo memoria
Djkt_nodo* Cdijkstra_arch::get_b( int iref, int ibloq, Djkt_nodo* buf/*=NULL*/)
{
	HANDLE hfile = INVALID_HANDLE_VALUE;
	int nb, i, nbt, j;
	char p[MAX_PATH];
	void *pun[3];
	Djkt_nodo* buf_res=NULL;
	BOOL no_ang;
	sprintf_s(p,MAX_PATH,"%s_%ld.%s",path,iref,extension);
	if(nod_amb<=ibloq)
		ibloq=0;
	if(ibloq<0 || iref<0)
		return NULL;
	Head_dj_arch hdl;
	//abre archivo-------------------------------------------------
	hfile = CreateFile(p,  GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error al abrir archivo: %s", p);
		goto va_mal;
	}
	//lee cabecera-------------------------------------------------
	nb=sizeof(hdl);
	if (nb != _lread((int)hfile,&hdl, nb))
	{
		//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error al leer cabecera archivo: %s", p);

		goto va_mal;
	}
	if(hdl.nb<ibloq)
	{
		//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error bloque %ld  (cab.nb %ld)no existe en  archivo: %s",ibloq,hdl.nb,  p);

		goto va_mal;
	}
	if(!buf)
	{
		//pide memoria-------------------------------------------------
		buf_res=(Djkt_nodo*)malloc(sizeof(Djkt_nodo)*hdl.nn);
		if(!buf_res)
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error sin memo para buffer archivo: %s", p);

			goto va_mal;
		}
		memset(buf_res,0,sizeof(Djkt_nodo)*hd.nn);

	}
	else
		buf_res=buf;
	//va al bloque correspondiente---------------------------------
	nb=sizn*hdl.nn*ibloq;
	if ( SetFilePointer(hfile, nb, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
		goto va_mal;
	for (i=0; i<hdl.nn; i++)
	{
		//guarda punteros de memo--------------
		if(buf)
		{
			pun[0]=buf_res[i].ids_ady.ids_padre;
			pun[1]=buf_res[i].ids_ady.i_conjs;
			pun[2]=buf_res[i].ids_ady.angs;
		}
		nbt=nb=sizeof(Djkt_nodo);
		if (nb != _lread((int)hfile,&buf_res[i], nb))
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error al leer nodo %ld archivo: %s",i, p);

			goto va_mal;
		}
		no_ang=!buf_res[i].ids_ady.angs;
		if(!buf)
		{
			buf_res[i].ids_ady.i_conjs=NULL;
			buf_res[i].ids_ady.angs=NULL;
			buf_res[i].ids_ady.ids_padre=NULL;
			//pide memoria para resto punteros------------------------
			if(!buf_res[i].ids_ady.inicia(buf_res[i].ids_ady.nady, no_ang) ||!buf_res[i].ids_ady.inicia_ids())
			{
				//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error al iniciar memoria nodo %ld archivo: %s",i, p);

				goto va_mal;
			}
		}
		else
		{	
			buf_res[i].ids_ady.ids_padre=(Djkt_ids_pdr*)pun[0];
			buf_res[i].ids_ady.i_conjs=(int*)pun[1];
			buf_res[i].ids_ady.angs=(BYTE**)pun[2];
			
			no_ang=no_ang || (buf_res[i].ids_ady.angs==NULL);
		}
		if(buf_res[i].ids_ady.nady<=0 || salta_ids_padres)
		{
			buf_res[i].ids_ady.nady=0;
			
			goto sigue;
		}
		
		nb=buf_res[i].ids_ady.nady*sizeof(Djkt_ids_pdr);
		if (nb != _lread((int)hfile, buf_res[i].ids_ady.ids_padre, nb))
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error al leer ids_padre en nodo %ld archivo: %s", i, p);

			goto va_mal;
		}
		nbt+=nb;
		nb=buf_res[i].ids_ady.nady*sizeof(int);
		
		if (nb != _lread((int)hfile, buf_res[i].ids_ady.i_conjs, nb))
		{
			//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error al leer i_conjs en nodo %ld archivo: %s", i, p);

			goto va_mal;
		}
		nbt+=nb;
		if(!no_ang)
		{
			nb=buf_res[i].ids_ady.nady*sizeof(BYTE);
			for (j=0; j<buf_res[i].ids_ady.nady; j++)
			{
				if (nb != _lread((int)hfile,buf_res[i].ids_ady.angs[j], nb))
				{
					//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error al leer angs %ld en nodo %ld archivo: %s", j, i, p);

					goto va_mal;
				}
				nbt+=nb;
			}
		}
sigue:
		//salta al siguiente------------------
		nb=sizn-nbt;
		if(nb>0)
		{
			if ( SetFilePointer(hfile, nb, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR)
			{
				//wgeotext(LOG_TODO,"Cdijkstra_arch::get_b","Error al ir al siguiente nodo, en nodo %ld archivo: %s", i, p);

				goto va_mal;
			}
		}
	}
	if(hfile != INVALID_HANDLE_VALUE)
		CloseHandle(hfile);
	return buf_res;
va_mal:
	if(hfile != INVALID_HANDLE_VALUE)
		CloseHandle(hfile);
	if(buf_res && !buf)
	{
		for (i=0; i<hd.nn; i++)
			buf_res[i].libera();
		free(buf_res);
	}
	return NULL;
}
//*************************************************************************************
BOOL Cdijkstra_arch::inicia_inf_amb( InfoIndice* ina, int namb, int tip_amb, int idinstal/*=-1*/, int idplan/*=-1*/ )
{
	float *buf;
	int i;
	ia=ina;
	nnod=namb;
	nod_amb=tip_amb;
	nnod=nnod*nod_amb;
	nambi=namb;
	nod_instal=idinstal;
	nod_plan=idplan;

	if(idplan>=0)
	{
		nnod++;
		id_plan=namb++;
		
	}
	if(idinstal>=0)
	{
		nnod++;
		id_instal=namb;
	}
	
	//pide memoria
	buf=(float*)realloc(dis,nnod*nnod*sizeof(float) );
	if(!buf)
	{
		ia=NULL;
		return FALSE;//sin memoria
	}
	dis=buf;
	for(i=nnod*nnod-1; i>=0; i--)
	{
		dis[i]=(float)MAYUSCULO;
	}
	return TRUE;

}
//*************************************************************************************
void Cdijkstra_arch::pon_info_amb( Djkt_nodo* nodos, int iref,int ib )
{
	int i, j, k;
	if(!ia)
		return;
	//calcula fila---
	j=(iref*nod_amb+ib)*nnod;
#ifdef DEBUG
	if (!AfxCheckMemory())
		C_log::log("Cdijkstra_arch","Error memoria");

#endif 
	for (i=0; i<nambi; i++)
	{
		for(k=0; k<nod_amb; k++)
		{
			dis[j+i*nod_amb+k]=nodos[ia->get(i,k)].dis;
			if(nodos[ia->get(i,k)].dis<0)
				nodos[ia->get(i,k)].dis=nodos[ia->get(i,k)].dis;
		}
	}
#ifdef DEBUG
	if (!AfxCheckMemory())
		C_log::log("Cdijkstra_arch","Error memoria");

#endif 
	if(nod_instal>=0)
	{
		dis[j+nambi*nod_amb+id_instal-nambi]=nodos[nod_instal].dis;
		if(nodos[nod_instal].dis<0)
			nodos[nod_instal].dis=nodos[nod_instal].dis;
	}
#ifdef DEBUG
	if (!AfxCheckMemory())
		C_log::log("Cdijkstra_arch","Error memoria");

#endif 
	if(nod_plan>=0)
	{
		dis[j+nambi*nod_amb+id_plan-nambi]=nodos[nod_plan].dis;
		if(nodos[nod_plan].dis<0)
			nodos[nod_plan].dis=nodos[nod_plan].dis;
	}
#ifdef DEBUG
	if (!AfxCheckMemory())
		C_log::log("Cdijkstra_arch","Error memoria");

#endif 
}
//*************************************************************************************
float Cdijkstra_arch::dame_dis( int aorig,int norig, int ades, int n_des )
{
	int i=aorig-nambi;
	if(nod_amb<=norig)
		norig=0;
	if(nod_amb<=n_des)
		n_des=0;
	if(i<0)
		i=0;
	aorig-=i;
	return dis[(ades*nod_amb+n_des)*nnod + aorig*nod_amb+norig+i];
}
//*************************************************************************************
BOOL Cdijkstra_arch::graba_dis(int id)
{
	Cgarray<float> buf;
	char p[MAX_PATH];
	sprintf(p,"%s_%ld.%s", path, id,TASKS_EXT_DIS);
	Cb_file f;
	if(!f.abre(p,2,TRUE))
		return FALSE;
	buf.ptr=dis;
	buf.n =nnod*nnod;
	BOOL res =buf.graba(&f);
	buf.ptr=NULL;
	buf.n =0;
	return res;

}
//*************************************************************************************
BOOL Cdijkstra_arch::lee_dis()
{
	Cb_file f;
	StrArray files;
	char sext[MAX_PATH];
	strcpy(sext, path);
	Cgarray<float> buf;
	//pilla archivos-----------------------
	if(!Cdir_manager::listar(Cdir_manager::dir_anterior(sext), &files))
		return FALSE;
	char *file;
	for (int i = 0; i<files.size(); i++)
	{
		file=files.get(i);

		if(strcmp(Cdir_manager::extension_archivo(file),TASKS_EXT_DIS))	
			continue;
		//leer
		if(!f.abre(file,1,FALSE,TRUE))
			return FALSE;
		buf.n=0;
		if(!buf.leer(&f))
			return FALSE;
		f.cierra();
		if(buf.n!= nnod*nnod)
			return FALSE;
		//mix---------------------------------------------
		for(int ii = 0; ii<buf.n; ii++)
			dis[ii]=min(dis[ii],buf[ii]);
	}		
	return TRUE;
}