#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;i16) { nady=nady; } //malloc i_conjs=(int*)malloc(nady*sizeof(int)); if(!i_conjs) return FALSE; for(i=0;iii) && (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;idimensiona(((__int64)n)*n)) goto va_mal; visto_ang->setAll(FALSE); if(angs) { ang_ok=TRUE; for (i=0; iset(((__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;jj1)) 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=0 && nn0; } 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; i0) { 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=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; iget(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 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 buf; //pilla archivos----------------------- if(!Cdir_manager::listar(Cdir_manager::dir_anterior(sext), &files)) return FALSE; char *file; for (int i = 0; i