#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;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;i0; } 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; i0) { 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 *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=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 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 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])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= 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;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[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=0 && nniold) { if(i1) res*=i--; return res; } #endif //*************************************************************************************