Olivia_v2017/Olivia/olv_geom.cpp

1466 lines
34 KiB
C++

#include "stdafx.h"
#ifdef OLIVIA_COMPILA
//olivia
#include "olv_geom.h"
#include "olv.h"
#include "olv_limp.h"
#include "math.h"
//otros
#include "olv_tasks_def.h"
#include "dir_manager.h"
#include "StrArray.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;
}
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
Cdijkstra_arch::Cdijkstra_arch()
{
memset(&hd, 0, sizeof(hd));
path[0]=0;
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*/, 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--------------------------------------
strcpy_s(st,1024,path_arch);
//pilla archivos-----------------
Cdir_manager::borra_archivos(Cdir_manager::dir_anterior(st),EXT_ARCH_DIJ_DEFAULT);
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,EXT_ARCH_DIJ_DEFAULT);
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,EXT_ARCH_DIJ_DEFAULT);
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)
{
olvlog(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))
{
olvlog(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))
{
olvlog(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)
{
olvlog(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))
{
olvlog(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))
{
olvlog(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))
{
olvlog(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))
{
olvlog(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))
{
olvlog(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)
{
olvlog(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))
{
olvlog(LOG_TODO,"Cdijkstra_arch::add_b","Error al escrivir cabecera, archivo: %s", p);
goto va_mal;
}
CloseHandle(hfile);
if(pon_inf)
{
pon_info_amb(blq, iref, inod);
}
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,EXT_ARCH_DIJ_DEFAULT);
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)
{
olvlog(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))
{
olvlog(LOG_TODO,"Cdijkstra_arch::get_b","Error al leer cabecera archivo: %s", p);
goto va_mal;
}
if(hdl.nb<ibloq)
{
olvlog(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)
{
olvlog(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))
{
olvlog(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())
{
olvlog(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))
{
olvlog(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))
{
olvlog(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))
{
olvlog(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)
{
olvlog(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( std::map<int,Info_aso2> *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;
for (i=0; i<nambi; i++)
{
for(k=0; k<nod_amb; k++)
{
dis[j+i*nod_amb+k]=nodos[(*ia)[i].inod[k]].dis;
if(nodos[(*ia)[i].inod[k]].dis<0)
nodos[(*ia)[i].inod[k]].dis=nodos[(*ia)[i].inod[k]].dis;
}
}
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;
}
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;
}
}
//*************************************************************************************
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))
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;
}
//*************************************************************************************
//*************************************************************************************
//*************************************************************************************
//Funciones de la clase geom
Colv_geom::Colv_geom(void)
{
}
Colv_geom::~Colv_geom(void)
{
}
//**************************************************************************************************************************
/*
* Devuelve el ángulo entre v1 y v2
*/
double Colv_geom::ang_vect(double v1[2], double v2[2])
{
double res = sqrt(v1[0] * v1[0] + v1[1] * v1[1]) *
sqrt(v2[0] * v2[0] + v2[1] * v2[1]);
if(res==0)
return 0;
res = (v1[0] * v2[0] + v1[1] * v2[1]) / res;
if (res > 1)
res = 1;
if (res < -1)
res = -1;
return acos(res);
}
//*************************************************************************************
/**
* Devuelve true si los puntos son iguales, false si no
*/
BOOL Colv_geom::pto_equals(double pt1[3], double pt2[3], BOOL d3 /*=false*/)
{
BOOL c3;
if(d3)
c3=(fabs(pt1[2]-pt2[2])<OLV_DIF_MAX_MISMA_COOR);
else
c3=TRUE;
return ((fabs(pt1[0]-pt2[0])<OLV_DIF_MAX_MISMA_COOR) &&
(fabs(pt1[1]-pt2[1])<OLV_DIF_MAX_MISMA_COOR) && c3);
}
//*************************************************************************************
/**
* Dado un lineal, genera uno paralelo a una distancia dis dada, a la derecha si es d>0 o a la izquierda si d<0
*/
BOOL Colv_geom::haz_paralela(double (*ptos_orig)[3],int _np,double dis,double (**ptos_par)[3])
{
if(dis==0)
{
ptos_par=&ptos_orig;
return TRUE;
}
double (*v_unitario)[][3];
double (*ptos_salida)[][3];
double (*ptos)[][3];
int np,i;
double c,s,l,a1,a2,b1,b2,c1,c2,det,x,y;
np=_np;
ptos_salida=(double (*)[][3])malloc(sizeof(double)*3*np);
if(!ptos_salida)
return FALSE;
memset(ptos_salida,0,sizeof(double)*3*np);
ptos=(double (*)[][3])malloc(sizeof(double)*3*np);
if(!ptos)
return FALSE;
memcpy(ptos,ptos_orig,sizeof(double)*3*np);
v_unitario=(double (*)[][3])malloc(sizeof(double)*3*(np-1));
if(!v_unitario)
return FALSE;
//d distancia, positivo -> paralela a la izquierda , negativo a la derecha
//el array (*v_unitario) tiene los vectores unitarios de cada direccion
for (i=0;i<=(np-2);i++)
{
c= (*ptos)[i+1][0]-(*ptos)[i][0] ;
s = (*ptos)[i+1][1]-(*ptos)[i][1];
l = sqrt(c*c+s*s);
if(l==0)
l=1;
(*v_unitario)[i][0]= c/l;
(*v_unitario)[i][1]=s/l;
}
// calculamos la normal para el primer punto
(*ptos_salida)[0][0]=(*ptos)[0][0]-dis*(*v_unitario)[0][1];
(*ptos_salida)[0][1]=(*ptos)[0][1]+dis*(*v_unitario)[0][0];
// desde 1 hasta np-1 calculamos la interseccion de las lineas
for (i=1;i<=(np-2);i++)
{
l = dis/(1+(*v_unitario)[i][0]*(*v_unitario)[i-1][0]
+(*v_unitario)[i][1]*(*v_unitario)[i-1][1]) ;
(*ptos_salida)[i][0]=(*ptos)[i][0]
- l*((*v_unitario)[i][1]+(*v_unitario)[i-1][1]);
(*ptos_salida)[i][1]=(*ptos)[i][1]
+ l*((*v_unitario)[i][0]+(*v_unitario)[i-1][0] );
}
// usamos la normal para el ultimo punto
(*ptos_salida)[np-1][0]= (*ptos)[np-1][0]- dis*(*v_unitario)[np-2][1];
(*ptos_salida)[np-1][1]= (*ptos)[np-1][1] + dis*(*v_unitario)[np-2][0];
//si el ultimo punto tiene las mismas coordenadas que el primero es un superficial
//en los superficiales se une el primero con el último
if ((*ptos)[np-1][0]==(*ptos)[0][0] &&(*ptos)[np-1][1]==(*ptos)[0][1])
{
// el punto inicial y final se intersectan. Solucion ideal para superficiales
a1 = (*ptos_salida)[np-1][1]-(*ptos_salida)[np-2][1];
b1 = (*ptos_salida)[np-2][0]-(*ptos_salida)[np-1][0];
c1 = a1*(*ptos_salida)[np-2][0]+b1*(*ptos_salida)[np-2][1];
a2 = (*ptos_salida)[0][1]-(*ptos_salida)[1][1];
b2 = (*ptos_salida)[1][0]-(*ptos_salida)[0][0];
c2 = a2*(*ptos_salida)[1][0]+b2*(*ptos_salida)[1][1];
det = a1*b2 - a2*b1;
x = (b2*c1 - b1*c2)/det;
y = (a1*c2 - a2*c1)/det;
(*ptos_salida)[np-1][0]=x;
(*ptos_salida)[np-1][1]=y;
(*ptos_salida)[0][0]=x;
(*ptos_salida)[0][1]=y;
}
free(v_unitario);
free(ptos);
///Fin de los arcos intermedios
*ptos_par=(double(*)[3]) ptos_salida;
return TRUE;
}
//*************************************************************************************
/**
* 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 Colv_geom::dijkstra_ang_inv_ok(CmapMatFloat &costes, Djkt_ang_ady *angs, int n, int fin, Djkt_nodo **nodos, BYTE **visto_ang_)
{
int i, sig,sigr;
Djkt_cola q;
BOOL res=FALSE;
Djkt_nodo *distancias;
double d;
BOOL ang_ok;
//BYTE ang;
int id_inci;
BYTE *visto_ang=NULL;
int ii,jj;
q.inicia(NULL);
distancias = *nodos;
if(!distancias)
distancias = (Djkt_nodo*)malloc(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));
if(!visto_ang)
goto va_mal;
memset(visto_ang,0,n*n*sizeof(BYTE));
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[id_inci*n+sig])
continue;
visto_ang[id_inci*n+sig]=1;
//se revisa cada nodo
for (i = 0; i < n; i++)
{
if (costes[i][sig] >= MAYUSCULO)
continue;
if (visto_ang[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[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[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);
if(visto_ang_)
{
*visto_ang_=visto_ang;
visto_ang=NULL;
}
if (visto_ang)
free(visto_ang);
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 Colv_geom::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 Colv_geom::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;
}
//*************************************************************************************
/**
* Devuelve la posición del elemento i-ésimo si se cambia la posición iold por la inew
*/
int Colv_geom::dame_ind_per(int i, int iold, int inew)
{
if(i==inew)
return iold;
if(i<iold)
{
if(i<inew)
return i;
return i-1;
}
else if(i>iold)
{
if(i<inew)
return i+1;
return i;
}
else
{
if(i<inew)
return i+1;
return i-1;
}
}
//*************************************************************************************
int Colv_geom::dame_n_nucleos()
{
//return 1;
SYSTEM_INFO sys;
GetSystemInfo(&sys);
return max(sys.dwNumberOfProcessors,1);
}
//*************************************************************************************
/**
* Devuelve el factorial de i, OJO usar con moderación
*/
int Colv_geom::fact(int i)
{
int res=1;
while(i>1)
res*=i--;
return res;
}
#endif
//*************************************************************************************