#include "stdafx.h" #ifdef OLIVIA_COMPILA //olivia #include "olv_limp_thr.h" #include "olv_thr.h" #include "olv_limp.h" #include "olv.h" #include "olv_geom.h" #include "olv_csv.h" //igt_base #include "lock.h" #include #include "olv_tasks.h" #include "olv_tasks_def.h" #include "olv_sock.h" //utiles #include "dir_manager.h" #include "GeometryFunction.h" #include "Fdbf.h" #include "b_file.h" #include "ManagerDbfGdataTable.h" #include "sock_sv.h" #include UINT th_planificacion(LPVOID pp); /** * @file olv_limp_thr.cpp * Archivo de implementaciones del thread de control de la utilidad de limpieza viaria del programa Olivia. */ Colv_limp_thr::Colv_limp_thr(Colv_limp *olv_limp) : Colv_thr(olv_limp->olv) { this->olv_limp = olv_limp; thr_padre=NULL; n_subthr_fin=0; pirate=FALSE; fin_permu=FALSE; //los subthreads n_subthr=Colv_geom::dame_n_nucleos(); //lanza un thread por procesador subthrs = (Colv_limp_thr **)malloc(n_subthr*sizeof(Colv_limp_thr *)); for(int i=0;itramos=NULL; } Colv_limp_thr::~Colv_limp_thr(void) { int i; //destruye los subthreads if(subthrs) { for(i=0;itramos) delete [] olv_limp->tramos; } //************************************************************************************* void Colv_limp_thr::inicia_th() { inicia(OLV_MILIS_COLA,&cola_proc,-1,"limp_thr"); olvlog(LOG_TODO,"olv_limp_t","Thread de limpieza limp_thr arrancado"); borra_temp_files(); pirate=FALSE; fin_permu=FALSE; } //************************************************************************************* /** * Cola de procesos en la que el thread está iterando y va ejecutando la tarea que le toque en cada momento * También se usa en los subprocesos, cuando el proceso principal lanza los subprocesos, cada uno itera en una cola como esta */ void Colv_limp_thr::cola_proc(int evento, OlvAsync_cola *clase,Param_olv_limp_thr *e) { BOOL bien=TRUE; Colv_limp_thr *this_i=static_cast(clase); switch (evento) { case OLV_LIMP_EV_ABRE_DAT: { bien=this_i->abre_datos(); if(bien && (this_i->olv->modo_ejecpirate)//sigue this_i->encola(OLV_LIMP_EV_RELL_DAT,NULL,FALSE); break; } case OLV_LIMP_EV_RELL_DAT: { bien=this_i->rellena_datos(); if(bien && (this_i->olv->modo_ejecpirate)//sigue { if(!this_i->olv->olv_limp->barr_mix) this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE); else this_i->encola(OLV_LIMP_EV_BARRMIX,NULL,FALSE); } break; } case OLV_LIMP_EV_BARRMIX: { //esta tarea lanza varios subthreads para realizar las comprobaciones del barrido mixto //y estos cuando acaban le encolan al padre (el que los ha lanzado) //la tarea de comprueba_barr_mixto_fin this_i->mejora_barr_mix(); break; } case OLV_LIMP_EV_BARRMIX_SUB: { //aquí entran los subthreads para hacer las comprobaciones del barrido mixto //encolan al padre la tarea de fin int ithr; if(e!=NULL) ithr=e->id_e; this_i->mejora_barr_mix_sub(ithr); break; } case OLV_LIMP_EV_BARRMIX_FIN: { //aquí entra el padre cuando van acabando los subthreads //si han terminado todos encola la siguiente tarea this_i->n_subthr_fin++; if(this_i->n_subthr_fin==this_i->n_subthr) { this_i->n_subthr_fin=0; bien=this_i->mejora_barr_mix_fin(); if(bien && (this_i->olv->modo_ejecpirate)//sigue { this_i->encola(OLV_LIMP_EV_UNE_AMB_NW,NULL,FALSE); } } break; } case OLV_LIMP_EV_UNE_AMB_NW: { int soloi=-1; bien=this_i->une_amb_nw(soloi); if(bien && (this_i->olv->modo_ejecpirate)//sigue { if(this_i->olv_limp->tipo_ambit==OLV_AMB_LIN) this_i->encola(OLV_LIMP_EV_COMPCORT,NULL,FALSE); else //si son lineales, se mira si hay cortes para reapuntar antes de hacer topo this_i->encola(OLV_LIMP_EV_TOPO_NW,NULL,FALSE); } break; } case OLV_LIMP_EV_COMPCORT: { this_i->compr_cortes_amb(); break; } case OLV_LIMP_EV_COMPCORT_SUB: { //aquí entran los subthreads para hacer los cálculos de distancia, cuando acaban //encolan al padre la tarea de fin int ithr; if(e!=NULL) ithr=e->id_e; this_i->compr_cortes_amb_sub(ithr); break; } case OLV_LIMP_EV_COMPCORT_FIN: { //aquí entra el padre cuando van acabando los subthreads //si han terminado todos encola la siguiente tarea this_i->n_subthr_fin++; if(this_i->n_subthr_fin==this_i->n_subthr) { this_i->n_subthr_fin=0; bien=this_i->compr_cortes_amb_sub_fin(); if(bien && (this_i->olv->modo_ejecpirate)//sigue { this_i->encola(OLV_LIMP_EV_TOPO_NW,NULL,FALSE); } } break; } case OLV_LIMP_EV_TOPO_NW: { bien=this_i->topo_nw(); if(bien && (this_i->olv->modo_ejecpirate)//sigue this_i->encola(OLV_LIMP_EV_COST_CONJ,NULL,FALSE); break; } case OLV_LIMP_EV_COST_CONJ: { //esta tarea lanza varios subthreads para realizar los cálculos //de costes entre conjunciones (les encola la tarea dist_conj_sub), //y estos cuando acaban le encolan al padre (el que los ha lanzado) //la tarea de dist_conj_fin bien=this_i->calcula_cost_conj(); break; } case OLV_LIMP_EV_COST_CONJ_SUB: { //aquí entran los subthreads para hacer los cálculos de distancia, cuando acaban //encolan al padre la tarea de fin int ithr; if(e!=NULL) ithr=e->id_e; this_i->calcula_cost_conj_sub(ithr); break; } case OLV_LIMP_EV_COST_CONJ_FIN: { //aquí entra el padre cuando van acabando los subthreads //si han terminado todos encola la siguiente tarea this_i->n_subthr_fin++; if(this_i->n_subthr_fin==this_i->n_subthr) { this_i->n_subthr_fin=0; bien=this_i->calcula_cost_conj_fin(); if(bien && (this_i->olv->modo_ejecpirate)//sigue { this_i->encola(OLV_LIMP_EV_ANG_CONJ,NULL,FALSE); } } break; } case OLV_LIMP_EV_ANG_CONJ: { //esta tarea lanza varios subthreads para realizar los cálculos //de ángulos entre conjunciones (les encola la tarea ang_conj_sub), //y estos cuando acaban le encolan al padre (el que los ha lanzado) //la tarea de ang_conj_fin bien=this_i->calcula_ang_conj(); break; } case OLV_LIMP_EV_ANG_CONJ_SUB: { //aquí entran los subthreads para hacer los cálculos de ángulos, cuando acaban //encolan al padre la tarea de fin int ithr; if(e!=NULL) ithr=e->id_e; this_i->calcula_ang_conj_sub(ithr); break; } case OLV_LIMP_EV_ANG_CONJ_FIN: { //aquí entra el padre cuando van acabando los subthreads //si han terminado todos encola la siguiente tarea this_i->n_subthr_fin++; if(this_i->n_subthr_fin==this_i->n_subthr) { this_i->n_subthr_fin=0; bien=this_i->calcula_ang_conj_fin(); if(bien && this_i->olv_limp->olv->modo_multitask && !this_i->pirate) this_i->encola(OLV_LIMP_EV_GUARD_MATS,NULL,FALSE); else if(bien && (this_i->olv->modo_ejecpirate)//sigue this_i->encola(OLV_LIMP_EV_COST_AMB,NULL,FALSE); } break; } case OLV_LIMP_EV_GUARD_MATS: { bien=this_i->guarda_mats(); break; } case OLV_LIMP_EV_GUARD_MATS_SUB: { int ithr; if(e!=NULL) ithr=e->id_e; this_i->guarda_mats_sub(ithr); break; } case OLV_LIMP_EV_GUARD_MATS_FIN: { //aquí entra el padre cuando van acabando los subthreads //si han terminado todos encola la siguiente tarea this_i->n_subthr_fin++; int i; if(this_i->n_subthr_fin==this_i->n_subthr) { this_i->n_subthr_fin=0; for(i=0;in_subthr;i++) if(this_i->subthrs[i]->prog_subthr<0) break; if(in_subthr) { bien=FALSE; this_i->pon_mi_msg("Errores al guardar matrices de costes"); break; } bien=this_i->guarda_mats_fin(); if(bien && (this_i->olv->modo_ejecpirate)//sigue this_i->encola(OLV_LIMP_EV_TASK_ESCUCHA,NULL,FALSE); } break; } case OLV_LIMP_EV_TASK_ESCUCHA: { bien=this_i->task_dj_escucha(); break; } case OLV_LIMP_EV_TASK_FIN: { this_i->n_subthr_fin++; if((e!=NULL) && e->id_e<0)//ha ido mal { if(e->id_e==-1) this_i->subthrs[this_i->n_subthr_fin-1]->prog_subthr=-1; else if(e->id_e==-2) { bien=FALSE; this_i->pon_mi_msg("Errores en cálculo multitask, no ha habido conexión"); break; } } int i; if(this_i->n_subthr_fin==this_i->n_subthr) { this_i->n_subthr_fin=0; for(i=0;in_subthr;i++) if(this_i->subthrs[i]->prog_subthr<0) break; if(in_subthr) { bien=FALSE; this_i->pon_mi_msg("Errores en cálculo multitask"); break; } this_i->task_dj_fin(); if(bien && (this_i->olv->modo_ejecpirate)//sigue this_i->encola(OLV_LIMP_EV_COST_AMB,NULL,FALSE); } break; } case OLV_LIMP_EV_COST_AMB: { //esta tarea lanza varios subthreads para realizar los cálculos //de costes(les encola la tarea dist_amb_sub), //y estos cuando acaban le encolan al padre (el que los ha lanzado) //la tarea de dist_amb_fin bien=this_i->calcula_cost_amb(); break; } case OLV_LIMP_EV_COST_AMB_SUB: { //aquí entran los subthreads para hacer los cálculos de costes entre ámbitos, cuando acaban //encolan al padre la tarea de fin int ithr; if(e!=NULL) ithr=e->id_e; this_i->calcula_cost_amb_sub(ithr); break; } case OLV_LIMP_EV_COST_AMB_FIN: { //aquí entra el padre cuando van acabando los subthreads //si han terminado todos encola la siguiente tarea int i; this_i->n_subthr_fin++; if(this_i->n_subthr_fin==this_i->n_subthr) { this_i->n_subthr_fin=0; for(i=0;in_subthr;i++) if(this_i->subthrs[i]->prog_subthr<0) break; if(in_subthr) { bien=FALSE; this_i->pon_mi_msg("Errores al calcular coste entre ámbitos"); break; } bien=this_i->calcula_cost_amb_fin(); if(bien && (this_i->olv->modo_ejecpirate)//sigue { if(this_i->olv->modo_ejec==OLV_EJEC_PLAN) //lee info de sectorización y va a planif this_i->encola(OLV_LIMP_EV_LEE_SECTO,NULL,FALSE); else //sectoriza { if(this_i->olv_limp->nsec==0)//hay que calcular el número de sectores this_i->encola(OLV_LIMP_EV_CALC_NSEC,NULL,FALSE); else { if(this_i->olv_limp->nsec<0) { this_i->olv_limp->calc_nsec=this_i->dame_cost_jornada();//indica que se tiene que ajustar a la jornada this_i->olv_limp->nsec=this_i->olv_limp->nsec_act=this_i->olv_limp->nsec*(-1); } this_i->encola(OLV_LIMP_EV_SECTORIZA,NULL,FALSE); } } } } break; } case OLV_LIMP_EV_CALC_NSEC: { bien=this_i->calcula_n_sec(); if(bien && (this_i->olv->modo_ejecpirate)//sigue { this_i->encola(OLV_LIMP_EV_SECTORIZA,NULL,FALSE); } break; } case OLV_LIMP_EV_SECTORIZA: { bien=this_i->sectoriza(); if(bien && (this_i->olv->modo_ejecpirate)//sigue { this_i->pon_info_resul(); if(this_i->olv->modo_ejec>=OLV_EJEC_DEBUG_SIGUE) this_i->encola(OLV_LIMP_EV_PLANIFICA,NULL,FALSE); else { this_i->borra_temp_files(); this_i->pon_mi_progre(OLV_TAREA_FIN_SEC,0); } } break; } case OLV_LIMP_EV_LEE_SECTO: { bien=this_i->lee_secto(); if(bien && !this_i->pirate)//sigue { this_i->encola(OLV_LIMP_EV_PLANIFICA,NULL,FALSE); } break; } case OLV_LIMP_EV_PLANIFICA: { bien=this_i->planifica(); break; } case OLV_LIMP_EV_PLANIFICA_SUB: { //aquí entran los subthreads para hacer los cálculos de planificación, cuando acaban //encolan al padre la tarea de fin int ithr; if(e!=NULL) ithr=e->id_e; this_i->planifica_sub_1(ithr, this_i->olv_limp->cost_amb); break; } case OLV_LIMP_EV_PLANIFICA_FIN: { //aquí entra el padre cuando van acabando los subthreads //si han terminado todos encola la siguiente tarea int i; this_i->n_subthr_fin++; if(this_i->n_subthr_fin==this_i->n_subthr) { this_i->n_subthr_fin=0; for(i=0;in_subthr;i++) { if(this_i->subthrs[i]->prog_subthr<0) { break; } } if(in_subthr) { bien=FALSE; this_i->pon_mi_msg("Errores al planificar th %ld",i); break; } bien = this_i->planifica_fin(); //pone progreso como que ha terminado if(bien) { this_i->pon_info_resul(); this_i->borra_temp_files(); this_i->pon_mi_progre(OLV_TAREA_FIN_PLANIF,0); } } break; } case OLV_LIMP_EV_SUBTHR_PROG: { //aquí entra el padre porque le encolan los subthreads para avisarle del progreso double pro=0; for(int i=0;in_subthr;i++) pro+=this_i->subthrs[i]->prog_subthr; pro=OliviaDef::GeneralDef::ProgrMax*pro/this_i->n_subthr; if(e!=NULL) { this_i->pon_mi_progre(e->id_e,(int)pro); } break; } } if(!bien) { this_i->pon_mi_progre(OLV_TAREA_FIN_NOK,0); #ifndef _DEBUG this_i->borra_temp_files(); #endif } } //************************************************************************************* void Colv_limp_thr::termina_th() { if(tarea==OLV_TAREA_PERMU && !fin_permu) { fin_permu=TRUE; return; } if(fin_permu) fin_permu=FALSE; pirate=TRUE; para_subthrs(); termina(); olvlog(LOG_TODO,"olv_limp_t","Thread de limpieza limp_thr finalizado"); } //************************************************************************************* /** * Abre los datos de cartografía */ BOOL Colv_limp_thr::abre_datos() { //////////////////////////////////////////////////////// int i; Info_aso2 info_aux; CartoBaseInfoEntity ient; olvlog(LOG_TODO,"olv_limp_t","Abriendo datos"); pon_mi_progre(OLV_TAREA_IMP, 0); pon_mi_msg(""); err_str[0]=0; //abre la cartografía con los datos if(!olv_limp->carto.importShp(olv_limp->olv->paths.path_data)) { pon_mi_msg("Error en la importación del archivo\n%s",olv_limp->olv->paths.path_data); return FALSE; } olv_limp->n_amb=olv_limp->carto.getNumberEntities(); if(olv_limp->n_amb>=USHRT_MAX) { pon_mi_msg("Número de ámbitos (%ld) mayor que el permitido (%ld)\n",olv_limp->n_amb,USHRT_MAX); return FALSE; } //Inicializa la información asociada info_aux.reset(); //si es tipo eje de calle lo pone en el flag if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) { info_aux.flgs = OLV_LIMP_FLG_EJE; } info_aux.flgs |= OLV_LIMP_FLG_AMB; for(i=0;in_amb;i++) { ient = olv_limp->carto.get(i); info_aux.refe = ient.entity()->ref; info_aux.iamb=i; olv_limp->iaso[info_aux.refe]=info_aux; } //abre la cartografía de la red navegable if(!olv_limp->carto.importShp(olv_limp->olv->paths.path_nw)) { pon_mi_msg("Error en la importación del archivo\n%s",olv_limp->olv->paths.path_nw); return FALSE; } olv_limp->n_nw=olv_limp->carto.getNumberEntities()-olv_limp->n_amb; //Inicializa la información asociada info_aux.reset(); info_aux.flgs = OLV_LIMP_FLG_NW; for(i=olv_limp->n_amb;in_nw+olv_limp->n_amb;i++) { ient=olv_limp->carto.get(i); info_aux.refe = ient.entity()->ref; olv_limp->iaso[info_aux.refe]=info_aux; } ////////////////////////////////////////////////////////////////////////// //rellena la información asociada de la red: //sentidos de circulación, velocidad de la vía... if(!rellena_info_nw()) { pon_mi_msg("Error al leer info asociada a red navegable: %s", err_str); return FALSE; } //////////////////// olvlog(LOG_TODO,"olv_limp_t","Finaliza Abrir datos con éxito"); return TRUE; } //************************************************************************************* /** * Rellena la información asociada de la red navegable y los datos de limpieza */ BOOL Colv_limp_thr::rellena_datos() { if(!rellena_info_amb()) { pon_mi_msg("Error al leer info asociada a ámbitos: %s", err_str); return FALSE; } olvlog(LOG_TODO,"olv_limp_t","Finaliza Rellena datos con éxito"); return TRUE; } //************************************************************************************* /** * Comrpueba las entidades para adecuarlas al barrido mixto */ void Colv_limp_thr::mejora_barr_mix() { int nthr=n_subthr; olvlog(LOG_TODO,"olv_limp_t","Comienza las comprobaciones para el barrido mixto"); lanza_subthrs(OLV_LIMP_EV_BARRMIX_SUB,nthr); } //************************************************************************************* /** * Comrpueba las entidades para adecuarlas al barrido mixto */ BOOL Colv_limp_thr::mejora_barr_mix_fin() { //////////////// //para los threads para_subthrs(); return TRUE; } //************************************************************************************* /** * Comrpueba las entidades para adecuarlas al barrido mixto */ void Colv_limp_thr::mejora_barr_mix_sub(int ithr) { //recorre los ámbitos int i,j; int refe_ace, refe_otro, refe_ant; int na_desp,na_ini, na_fin, seg; double lon_ace, lon_otro, pond, lon_ant,da; BOOL mal=FALSE; BOOL paralelas; CartoBaseInfoEntity ient_ace, ient_otro; na_desp = (int)ceil(1.0*(olv_limp->n_amb)/n_subthr); na_ini= min(ithr*na_desp, olv_limp->n_amb); na_fin = min((ithr+1)*na_desp,olv_limp->n_amb); olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Comprueba Barr Mix Ambs %04d a %04d", ithr, na_ini, na_fin); seg = GetTickCount(); //Bucle en los ámbitos for(i=na_ini;icarto.get(i); refe_ace = ient_ace.entity()->ref; if(!(olv_limp->iaso[refe_ace].flgs & OLV_LIMP_FLG_AMB_ACE)) continue; //Se recorre las aceras //Por cada acera, se recorre el resto de entidades, y las que sean //bordillo o banda de aparcamiento, comprueba si es paralela for(j=0;jn_amb && !pirate; j++) { ient_otro = olv_limp->carto.get(j); refe_otro = ient_otro.entity()->ref; if((j==i) || !(olv_limp->iaso[refe_otro].flgs & (OLV_LIMP_FLG_AMB_APA|OLV_LIMP_FLG_AMB_BORD))) continue; //recorre ambas rectas a la par //para ello, primero mira cuál es la más larga lon_ace = ient_ace.getLong(); lon_otro = ient_otro.getLong(); //parte de la más corta, y avanza en pasos del PORC_AVANCE% de su longitud if(lon_aceiaso[refe_ace].refe2==-1) { //es la primera vez que ecuentra un bordillo paralelo olv_limp->iaso[refe_ace].flgs=olv_limp->iaso[refe_ace].flgs | OLV_LIMP_FLG_AMB_NO; while(olv_limp->iaso[refe_otro].refe2!=-1) { refe_otro=olv_limp->iaso[refe_otro].refe2; } olv_limp->iaso[refe_ace].refe2=refe_otro; } else { //esa acera ya tiene un bordillo paralelo, a este nuevo bordillo se le //marca para que no se haga, y se acumula al anterior refe_ant=olv_limp->iaso[refe_ace].refe2; //marca el nuevo como no olv_limp->iaso[refe_otro].flgs=olv_limp->iaso[refe_otro].flgs | OLV_LIMP_FLG_AMB_NO; //coge el anterior olv_limp->iaso[refe_otro].refe2=refe_ant; //le añade un delta de ancho al anterior para que compense la longitud del nuevo lon_ant=olv_limp->carto.getRef(refe_ant).getLong(); da=lon_otro*olv_limp->iaso[refe_otro].inf_l.ancho/lon_ant; olv_limp->iaso[refe_ant].inf_l.ancho+=da; //renombra el otro como el anterior, para añadirle la acera refe_otro=refe_ant; } //olv_limp->iaso[refe_ace].refe2=refe_otro; //suma los anchos de forma ponderada pond=lon_ace/lon_otro; if(pond>1) pond=1; //cuando la acera es más grande, se suma el ancho de la acera, no se amplia //cuando la acera es más pequeña, puede que en ese bordillo o banda de aparcamiento //haya otra acera en paralelo, así que se le sumará después su ancho también, //de forma que la suma total sea la ponderación de los anchos olv_limp->iaso[refe_otro].inf_l.ancho += olv_limp->iaso[refe_ace].inf_l.ancho*pond; } //avisa de progreso if(((i-na_ini)%100==0) || ((i-na_ini)==(na_desp-1))) { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Comprobando Barrido Mixto ambs %ld de %ld", ithr, (i-na_ini+1),na_desp); } } if(mal) { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en mejoras Barrido mixto", ithr); prog_subthr=-1;//para avisar al padre de que ha habido un error } else { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin mejoras Barrido mixto, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); } thr_padre->encola(OLV_LIMP_EV_BARRMIX_FIN,NULL,FALSE); } //************************************************************************************* /** * Avanza desde el primer punto de ient1 y el más próximo en ient2, * midiendo la distancia entre las dos rectas * devuelve si son paralelas o no en función de la dmedia y la desv */ BOOL Colv_limp_thr::barr_mix_paralelas(CartoBaseInfoEntity ient1, CartoBaseInfoEntity ient2) { const double PORC_AVANCE = 0.2; //avanza en pasos del porc % de la longitud de la línea pequeña //////////////////////////////////// double l_avan, dmed, desv, l_parc, long1, dis; int n; double pt[3]; //comprueba si las puede descartar porque estén muy lejos //mira si la distancia mínima del primer punto de ient1 a ient2 //es muy grande para descartar if((ient2.DisPtoLine(ient1.getPto(0))>OLV_BARRMIX_DMAX_DESC) && (ient2.DisPtoLine(ient1.getPto(ient1.getNumberPtos()-1))>OLV_BARRMIX_DMAX_DESC)) return FALSE; l_parc=0; long1=ient1.getLong(); l_avan=PORC_AVANCE*long1; n=(int)(1/PORC_AVANCE+0.5); dmed=desv=0; while(l_parcOLV_BARRMIX_DMED_MAX || desv>OLV_BARRMIX_DESV_MAX) return FALSE; return TRUE; } //************************************************************************************* /** * Copia en las aceras que no se han usado para sectorizar porque se han asignado a bordillos o * bandas de aparcamiento, el mismo sector que el bordillo que tienen asignado * modo 0 secto, modo 1 planif */ void Colv_limp_thr::copia_info_barr_mix() { for(int i=0;in_amb;i++) { if(!(olv_limp->iaso[i].flgs & OLV_LIMP_FLG_AMB_NO) || olv_limp->iaso[i].refe2<0) continue; olv_limp->amb_sec[i].sec=olv_limp->amb_sec[olv_limp->iaso[olv_limp->iaso[i].refe2].iamb].sec; olv_limp->amb_sec[i].iseq=olv_limp->amb_sec[olv_limp->iaso[olv_limp->iaso[i].refe2].iamb].iseq; } } //************************************************************************************* /** * Rellena la información de sentidos de circulación y velocidad de las vías * en la tabla de información asociada */ BOOL Colv_limp_thr::rellena_info_nw() { Cb_file file; Fdbf dbf; int n,ntf, nft, nboth, nno,s,ia; int icamps,icampv,icampn,icampf,f,idd, icampoid; char nfile[MAX_PATH]; char *sent; BOOL ret=TRUE,ispedestrian; olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de info asociada a carreteras"); pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax*1/3)); //1/32 porque ya ha hecho 1/3, que es la importación ntf=nft=nboth=nno=0; sent=NULL; //si no aplican los sentidos de circulación no se calculan, se ponen todos a todos sentidos if(olv_limp->res_circ==OLV_RES_NO) { olvlog(LOG_TODO,"olv_limp_t","No aplican sentidos de circulación, puestos todos a 'ambos'"); nboth=olv_limp->n_nw; } //lee dbf del shp strcpy_s(nfile,MAX_PATH,olv->paths.path_nw); char bufAux[256]; strcpy(nfile, Cdir_manager::cambia_extension_archivo(nfile,bufAux,".dbf")); //cambiaext(nfile,".shp",".dbf"); if(!file.abre(nfile,1) || !dbf.lee(&file)) { sprintf_s(err_str,OLV_MAX_ERR,"Error al abrir %s",nfile); olvlog(LOG_TODO,"olv_limp_t","Error al abrir %s",nfile); return FALSE; } //busca el campo del sentido "ONEWAY" y el de "KPH" icamps=icampv=icampn=icampf=-1; icamps=dbf.findCol(olv_limp->camps.campo_circ); icampv=dbf.findCol(olv_limp->camps.campo_velo); icampn=dbf.findCol(olv_limp->camps.campo_name); icampf=dbf.findCol(olv_limp->camps.campo_fow); if(icamps==-1 || icampv==-1 || icampn==-1 || icampf==-1) { sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s y/o %s y/o %s en\n%s",olv_limp->camps.campo_circ, olv_limp->camps.campo_velo,olv_limp->camps.campo_name,nfile); olvlog(LOG_TODO,"No encontrado campo %s y/o %s y/o %s en\n%s",olv_limp->camps.campo_circ, olv_limp->camps.campo_velo,olv_limp->camps.campo_name,nfile); return FALSE; } icampoid=dbf.findCol(olv_limp->camps.campo_oid); //////////////////////////////////////// sent = (char*)malloc(dbf.getSize(icamps)+1); if(!sent) return FALSE; sent[0]=0; idd =dbf.leeNexRow(); n=0; ia=olv_limp->n_amb;//la info aso de la nw empieza donde acaba la de los ámbitos while(idd == 1) { /////////////////////////////// ispedestrian=FALSE; if(olv_limp->res_circ!=OLV_RES_NO) { //("FOW" =3 OR "FOW">=7) AND ("ONEWAY" = 'N' OR "ONEWAY" = ' ' ) //si se cumple lo anterior, son como doble sentido pero no se replican ////////////////////////// //sentido de circulación strcpy(sent,dbf.getStr(icamps)); s=0; if(strcmp(sent,olv_limp->camps.atr_circ[OLV_ATR_CIRC_TF])==0) { s=OLV_LIMP_FLG_CIRC_TF; ntf++; } else if(strcmp(sent,olv_limp->camps.atr_circ[OLV_ATR_CIRC_FT])==0) { s=OLV_LIMP_FLG_CIRC_FT; nft++; } else if(strcmp(sent,olv_limp->camps.atr_circ[OLV_ATR_CIRC_NONE])==0) { //no aplica la restricción por ser servicio público, cómo se sabe si es de un único sentido? s=OLV_LIMP_FLG_CIRC_NONE; nno++; } else { nboth++; } /////////////////////////////// //fow f=dbf.getI(icampf); //solo mira si es pedestrian, f==14 if(f==atoi(olv_limp->camps.atr_circ[OLV_ATR_CIRC_PEDES]) || f==-1) { s=OLV_LIMP_FLG_CIRC_NONE; ispedestrian=TRUE; } /////////////////////////////// olv_limp->iaso[ia].flgs|=s; } /////////////////////////////// //velocidad if((olv_limp->iaso[ia].flgs & OLV_LIMP_FLG_CIRC_NONE) || ispedestrian) { s= OLV_LIMP_VELO_CIRC_PEAT; //se le pone velo muy bajita para que intente no ir por ahí, porque son calles prohibidas //a no ser que haya un contenedor //o si es peatonal igual, que no haga las rutas por ahí, pero sí pase a hacer tratamientos } else { s=dbf.getI(icampv); } if(s<=0) { s=OLV_LIMP_VELO_DEF;//pone por def } olv_limp->iaso[ia].inf_n.velo=1.0*s*OLV_KMH2MS; /////////////////////////////// //nombre olv_limp->iaso[ia].inf_n.nomb = (char*)malloc(dbf.getSize(icampn)+1); if(!olv_limp->iaso[ia].inf_n.nomb) break; strcpy(olv_limp->iaso[ia].inf_n.nomb,dbf.getStr(icampn)); if(icampoid>=0) olv_limp->iaso[ia].oid = dbf.getI(icampoid); /////////////////////////////// //avisa de progreso if((n%200==0) || (n==(olv_limp->n_nw+olv_limp->n_amb-1))) { pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax* (1.0*(n+1)/olv_limp->n_nw/3)+1/3));//por 2/3 porque esta tarea es la 2/3 olvlog(LOG_TODO,"olv_limp_t","Rellenando info asociada a nw, %ld de %ld", n+1,olv_limp->n_nw); } ia++; n++; idd =dbf.leeNexRow(); } if(nn_nw) { sprintf_s(err_str,OLV_MAX_ERR,"Error al leer record %ld en\n%s",ia,nfile); ret=FALSE; goto fin; } olvlog(LOG_TODO,"olv_limp_t","Finaliza matriz de info asociada a carreteras: %ld doble sentido, %ld TF, %ld FT, %ld ninguno, %ld de %ld", nboth,ntf,nft, nno, nboth+ntf+nft+nno, olv_limp->n_nw); fin: if(sent) free(sent); return ret; } //************************************************************************************* /** * Rellena la información de ancho de los ámbitos * en la tabla de información asociada */ BOOL Colv_limp_thr::rellena_info_amb() { Cb_file f; Fdbf dbf; int icampa,icampo,icampta,icampte,idd,ia, icampoid; char *tipent, *tipap, *obs,*anc; double ancho; BOOL ret=TRUE,modo_ejes=FALSE; int barr_mix=0; char nfile[MAX_PATH]; //en principio, tipos puntuales no tienen info asociada if(olv_limp->tipo_ambit==OLV_AMB_PUN) return TRUE; //cuando se ha enviado eje de calle, no se lee info asociada porque la tabla es de tomotom, no tiene info //tipo entidad ni nada.. if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) modo_ejes= TRUE; olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de info asociada a ámbitos"); pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax*2/3)); tipent=tipap=obs=anc=NULL; //lee dbf del shp strcpy_s(nfile,MAX_PATH,olv->paths.path_data); //cambiaext(nfile,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); if(!f.abre(nfile,1) || !dbf.lee(&f)) { pon_mi_msg("Error al abrir %s",nfile); ret=FALSE; goto fin; } //busca el campo de observaciones, de ancho_tipo, de tipo_entidad y tipología_aparc //limita el ancho del campo icampo=dbf.findCol(olv_limp->camps.campo_obs); icampa=dbf.findCol(olv_limp->camps.campo_anch); icampta=dbf.findCol(olv_limp->camps.campo_tipo_ap); icampte=dbf.findCol(olv_limp->camps.campo_tipo_ent); if(!modo_ejes && (icampa==-1 || icampo==-1 || icampta==-1 || icampte==-1)) { sprintf_s(err_str,OLV_MAX_ERR,"No encontrado campo %s y/o %s y/o %s\ny/o %s en\n%s",olv_limp->camps.campo_obs,olv_limp->camps.campo_anch, olv_limp->camps.campo_tipo_ap,olv_limp->camps.campo_tipo_ent,nfile); ret=FALSE; goto fin; } icampoid=dbf.findCol(olv_limp->camps.campo_oid); if(!modo_ejes) { tipent = (char*)malloc(dbf.getSize(icampte)+1); tipap = (char*)malloc(dbf.getSize(icampta)+1); obs = (char*)malloc(dbf.getSize(icampo)+1); anc = (char*)malloc(dbf.getSize(icampa)+1); if(!tipent || !tipap || !obs || !anc) return FALSE; } idd =dbf.leeNexRow(); ia=0; while(idd == 1) { if(!modo_ejes) { //si el campo tipo de entidad es banda_aparcamiento, el ancho es fijo, //en función de la tipología del aparcamiento //si no, hay que leer el ancho ancho=OLV_LIMP_ANCH_DEF; /////////////////////////////// strcpy(tipent,dbf.getStr(icampte)); if(strlen(tipent)>0 && strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_AP])==0) { //es banda de aparcamiento strcpy(tipap,dbf.getStr(icampta)); if(strlen(tipap)>0 && strcmp(tipap,olv_limp->camps.atr_tip_apa[OLV_ATR_TIP_AP_LIN])==0) { //es aparcamiento lineal, ancho fijo 2 ancho=olv_limp->anchos_def[OLV_ANCH_DEF_APLIN]; } else if(strlen(tipap)>0 && strcmp(tipap,olv_limp->camps.atr_tip_apa[OLV_ATR_TIP_AP_BAT])==0) { //es aparcamiento en batería, ancho fijo 4 ancho=olv_limp->anchos_def[OLV_ANCH_DEF_APBAT]; } //lo marca para saber si es barrido mixto olv_limp->iaso[ia].flgs |= OLV_LIMP_FLG_AMB_APA; if(!olv_limp->barr_mix && !(barr_mix & OLV_LIMP_FLG_AMB_APA)) barr_mix |= OLV_LIMP_FLG_AMB_APA; } else if(strlen(tipent)>0 && strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_BORD])==0) { //es bordillo libre ancho=olv_limp->anchos_def[OLV_ANCH_DEF_BORD]; //lo marca para saber si es barrido mixto olv_limp->iaso[ia].flgs |= OLV_LIMP_FLG_AMB_BORD; if(!olv_limp->barr_mix && !(barr_mix & OLV_LIMP_FLG_AMB_BORD)) barr_mix |= OLV_LIMP_FLG_AMB_BORD; } else if(strlen(tipent)>0) { //es acera o peatonal //hay que leer el ancho strcpy(obs,dbf.getStr(icampo)); strcpy(anc,dbf.getStr(icampa)); ancho = olv_limp->dame_ancho(obs,anc); if(strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_ACERA])==0) { if(ancho==0) ancho=olv_limp->anchos_def[OLV_ANCH_DEF_ACE];//acera //lo marca para saber si es barrido mixto olv_limp->iaso[ia].flgs |= OLV_LIMP_FLG_AMB_ACE; if(!olv_limp->barr_mix && !(barr_mix & OLV_LIMP_FLG_AMB_ACE)) barr_mix |= OLV_LIMP_FLG_AMB_ACE; } else if(strcmp(tipent,olv_limp->camps.atr_tip_ent[OLV_ATR_NOM_TIP_ENT_PEAT])==0) { if(ancho==0) ancho=olv_limp->anchos_def[OLV_ANCH_DEF_PEAT];//peatonal olv_limp->iaso[ia].flgs |=OLV_LIMP_FLG_AMB_PEAT; } else if(ancho==0) ancho = OLV_LIMP_ANCH_DEF; } olv_limp->iaso[ia].inf_l.ancho=ancho; /////////////////////////////// //avisa de progreso if((ia%100==0) || (ia==(olv_limp->n_amb-1))) { pon_mi_progre(OLV_TAREA_IMP, (int) (OliviaDef::GeneralDef::ProgrMax* ((1.0*(ia+1)/olv_limp->n_amb)/3)+2/3)); olvlog(LOG_TODO,"olv_limp_t","Rellenando info asociada a ámbitos, %ld de %ld", ia+1,olv_limp->n_amb); } if(!olv_limp->barr_mix) olv_limp->barr_mix=(barr_mix & (OLV_LIMP_FLG_AMB_APA | OLV_LIMP_FLG_AMB_BORD)) && (barr_mix & OLV_LIMP_FLG_AMB_ACE); } if(icampoid>=0) olv_limp->iaso[ia].oid = dbf.getI(icampoid); ia++; idd =dbf.leeNexRow(); } //olv_limp->barr_mix=FALSE; if(ian_amb) { sprintf_s(err_str,OLV_MAX_ERR,"Error al leer información asociada ia %ld OID %ld en\n%s", ia, olv_limp->iaso[ia].oid,nfile); ret=FALSE; goto fin; } olvlog(LOG_TODO,"olv_limp_t","Finaliza Matriz de info asociada a ámbitos"); fin: if(tipent) free(tipent); if(tipap) free(tipap); if(obs) free(obs); if(anc) free(anc); return ret; } //************************************************************************************* /** * Replica los ámbitos cuando son tipo peatonal, añadiendo otro lineal igual que tendrá solo coste * de desplazamiento, no de tratamiento, más los segmentos que los unen, de coste 0 */ BOOL Colv_limp_thr::replica_peat() { int i,j,k; CartoBaseInfoEntity ient, ientcp; CartoLine peatcp; Info_aso2 info_aux; double ptos[2][3]; CartoLine ptos_aux; ptos_aux.pts.n = 2; ptos_aux.pts.ptr = ptos; olvlog(LOG_TODO,"olv_limp_t","Replicando calles peatonales"); peatcp.idPropsP =0; for(i=0;in_amb; i++) { ient=olv_limp->carto.get(i); if(!(olv_limp->iaso[ient.entity()->ref].flgs & OLV_LIMP_FLG_AMB_PEAT)) continue; //Replica la peatonal if(!ient.getCopy(&peatcp) || !olv_limp->carto.add(peatcp)) break; ientcp=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1); //Añade la info aso info_aux.reset(); info_aux.flgs=OLV_LIMP_FLG_PEAT_REP; info_aux.refe=ientcp.entity()->ref; info_aux.refe2=ient.entity()->ref; olv_limp->iaso[info_aux.refe]=info_aux; //añade los dos extremos for(j=0;j<2;j++) { for(k=0;k<2;k++) { memcpy(ptos[k],ient.getPto(j),3*sizeof(double)); } //lo añade al carto olv_limp->carto.add(ptos_aux); ientcp=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1); //Añade la info aso info_aux.reset(); info_aux.flgs=OLV_LIMP_FLG_PEAT_SEG | (j*OLV_LIMP_FLG_FIN); info_aux.refe=ientcp.entity()->ref; info_aux.refe2=ient.entity()->ref; olv_limp->iaso[info_aux.refe]=info_aux; } } ptos_aux.pts.ptr = NULL; if(in_amb) return FALSE; return TRUE; } //************************************************************************************* /** * Replica las calles cuando son de doble sentido y se tienen en cuenta las restricciones * de circulación, para que se asignen los ámbitos sólo a la calle del sentido en el que estén */ BOOL Colv_limp_thr::replica_doble_sent(Info_inw_dmin *inww_ord) { int i,KK,iaux; unsigned short refnw; CartoBaseInfoEntity ientamb, ientcp, ientnw; CartoLine nwcp; Info_aso2 info_aux; if(olv_limp->res_circtipo_ambit; nwcp.idPropsP=0; //recorre los ámbitos viendo a qué calle están asignados, y si es a una //de doble sentido, se replica la calle y se pone cada una de un sentido, y se asigna //el ámbito a la calle de la que esté a la derecha //recorre el array de info nw for(i=0;in_amb*KK;i++) { refnw=inww_ord[i].refnw; if(!(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_NW) || (olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_CIRC_NO_DOB)) continue; ientamb = olv_limp->carto.getRef(inww_ord[i].refamb); ientnw = olv_limp->carto.getRef(refnw); //Replica la calle if(!ientnw.getCopy(&nwcp) || !olv_limp->carto.add(nwcp)) break; ientcp=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1); //le pone a la calle original que es solo FT olv_limp->iaso[refnw].flgs |= OLV_LIMP_FLG_CIRC_FT; //Añade la info aso de la copia info_aux.reset(); info_aux.flgs=OLV_LIMP_FLG_NW | OLV_LIMP_FLG_NW_REP | OLV_LIMP_FLG_CIRC_TF; info_aux.refe=ientcp.entity()->ref; //copia la velo y el nombre info_aux.inf_n.velo=olv_limp->iaso[refnw].inf_n.velo; info_aux.inf_n.nomb = (char*)malloc(strlen(olv_limp->iaso[refnw].inf_n.nomb)+1); if(!info_aux.inf_n.nomb) break; strcpy(info_aux.inf_n.nomb,olv_limp->iaso[refnw].inf_n.nomb); info_aux.refe2=refnw; //añade la info olv_limp->iaso[info_aux.refe]=info_aux; ////////////////////////////////////////////// //busca los ámbitos apuntados a ese nw, los que están a la izquiera les reapunta iaux=i; while((iauxn_amb*KK) && (inww_ord[iaux].refnw==refnw)) { if(!(olv_limp->iaso[inww_ord[iaux].refamb].flgs & OLV_LIMP_FLG_DER)) { inww_ord[iaux].refnw=info_aux.refe;//el lineal que acaba de añadir //reapunta también el original olv_limp->inww_amb[(int)inww_ord[iaux].alpha].refnw=info_aux.refe; ///////////////////////////// olv_limp->iaso[inww_ord[iaux].refamb].flgs |= OLV_LIMP_FLG_DER; } iaux++; } i=iaux-1; } if(in_amb*KK) return FALSE; return TRUE; } //************************************************************************************* /** * Une la red navegable y los ámbitos * 'soloi' es para debug, indica si se quiere realizar la unión de un único ámbito pasado en soloi */ BOOL Colv_limp_thr::une_amb_nw(int soloi) { int KK,i,refamb,k; CartoBaseInfoEntity iamb; BOOL comp_lejos,modo_ejes=FALSE; comp_lejos=(olv_limp->res_circuds_tto!=OliviaDef::GeneralDef::OlvTipTtoMh_eje) && (olv_limp->uds_tto!=OliviaDef::GeneralDef::OlvTipTtoM2h_eje)); //si es tipo ejes, lo hace de otra forma if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) { modo_ejes=TRUE; } ////////////////// //coge el factor del tipo de ámbito, 1 si es puntual, 2 si es lineal KK=olv_limp->tipo_ambit; ////////////////// //replica las peatonales que sea necesario if(KK==OLV_AMB_LIN) { if(!replica_peat()) { pon_mi_msg("Error al replicar peatonales"); return FALSE; } } ////////////////// //inicia cuando ya sabe si es tipo lineal o puntual if(!olv_limp->inww_amb) { olv_limp->inww_amb = (Info_inw_dmin *)malloc(olv_limp->n_amb*KK*sizeof(Info_inw_dmin)); } if(!olv_limp->inww_amb) { pon_mi_msg("Error, sin memoria para matriz de índices\nde ámbitos a carreteras"); return FALSE; } //rellena todos a no def for(i=0;in_amb*KK;i++) { olv_limp->inww_amb[i].reset(i%olv_limp->n_amb); } /////////////////// olvlog(LOG_TODO,"olv_limp_t","Uniendo ámbitos a NW"); pon_mi_progre(OLV_TAREA_UNE_NW_AMB, 0); pon_mi_msg(""); err_str[0]=0; //Bucle por ámbito for(i=0;in_amb && !pirate; i++) { if((soloi>-1) && (soloin_amb) && (i!=soloi)) continue;//para debug, si soloi apunta al ámbito que queremos calcular solo iamb = olv_limp->carto.getEntity(i); refamb=iamb.entity()->ref; if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_NO) continue; //rellena en inww_amb el inw y su info de la carretera del nw élegida como //más cercana al ámbito if(modo_ejes) busca_inw_dmin_ejes(i); else busca_inw_dmin(i); //////////////////////////////////////////// //comprueba en todos los ámbitos si va andando, si están asignados a una carretera muy lejos //y tienen un ámbito más cerca, les asigna ese (excepto en el caso ejes) if(comp_lejos) comprueba_amb_lejos(i); if((i%100==0) ||(i==(olv_limp->n_amb-1))) { olvlog(LOG_TODO,"olv_limp_t","Uniendo ámbitos a NW, %ld de %ld",i+1,olv_limp->n_amb); //avisa de progreso pon_mi_progre(OLV_TAREA_UNE_NW_AMB, (int) ((OliviaDef::GeneralDef::ProgrMax* (i+1)/olv_limp->n_amb)*((olv_limp->tipo_ambit==OLV_AMB_LIN ? 0.5 : 1)))); } } //cuida si ha salido antes por falta de memo if(in_amb) { pon_mi_msg("Error en la unión de ámbitos a red navegable"); return FALSE; } //Bucle por ámbito for(i=0;in_amb && !pirate; i++) { if((soloi>-1) && (soloin_amb) && (i!=soloi)) continue;//para debug, si soloi apunta al ámbito que queremos calcular solo iamb = olv_limp->carto.getEntity(i); refamb=iamb.entity()->ref; if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_NO) continue; //Añade los segmentos a clase NW_union add_uniones_obj(i); } //cuida si ha salido antes por falta de memo if(in_amb) { pon_mi_msg("Error en la unión de ámbitos a red navegable"); return FALSE; } if(comp_lejos) //ojo comprueba_aislados(olv_limp->inww_amb); ///////////////////////////////////////////////////// //si hay algún ámbito asignado a una carretera de prohibido circular //se le quita el flag a la carretera if(olv_limp->res_circ!=OLV_RES_NO) { for(i=0;in_amb && !pirate; i++) { refamb=olv_limp->carto.getEntity(i).entity()->ref; if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_NO) continue; for(k=0; kiaso[olv_limp->inww_amb[i + k*olv_limp->n_amb].refnw].flgs & OLV_LIMP_FLG_CIRC_NONE) { //le quita el flag olv_limp->iaso[olv_limp->inww_amb[i + k*olv_limp->n_amb].refnw].flgs = olv_limp->iaso[olv_limp->inww_amb[i + k*olv_limp->n_amb].refnw].flgs & ~OLV_LIMP_FLG_CIRC_NONE; } } } } return TRUE; } //************************************************************************************* /** * Como se ha podido unir unos ámbitos a otros, revisa que no se hayan unido sólo entre sí * y no a ninguna carretera, en ese caso estarían aislados. Lo revisa para, en esos casos, * forzar a que apunte alguno a una carretera */ void Colv_limp_thr::comprueba_aislados(Info_inw_dmin *inww) { int i,KK,iamb,k,j, refamb; BYTE *ambs_flgs; int *ambs_cola; int ncola; BOOL aislado; double dmin; int iambmin; #define FLG_VISTO 1 #define FLG_TEMP 2 KK=olv_limp->tipo_ambit; //inicia el array de flags ambs_flgs = (BYTE*)malloc(olv_limp->n_amb); if(!ambs_flgs) return; memset(ambs_flgs,0,olv_limp->n_amb); //inicia la cola ambs_cola = (int*)malloc(olv_limp->n_amb*sizeof(int)); if(!ambs_cola) return; memset(ambs_cola,0,olv_limp->n_amb*sizeof(int)); ncola=0; //bucle para cada ámbito for(i=0;in_amb && !pirate; i++) { if(ambs_flgs[i] & FLG_VISTO) continue; refamb=olv_limp->carto.getEntity(i).entity()->ref; if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_NO) continue; aislado=TRUE; //lo mete a la cola ambs_cola[ncola]=i; ncola=1; while (ncola) { //saca ámbito de la cola ncola--; iamb=ambs_cola[ncola]; //le pone el flag temporal ambs_flgs[iamb] |= FLG_TEMP; //bucle en los dos extremos for(k=0;kiaso[inww[iamb+k*olv_limp->n_amb].refnw].flgs & OLV_LIMP_FLG_NW)) { //lo mete en la cola si su extremo es un ámbito //no visto ni temporal if(ambs_flgs[inww[iamb+k*olv_limp->n_amb].refnw] & (FLG_TEMP | FLG_VISTO)) continue; ambs_cola[ncola]=inww[iamb+k*olv_limp->n_amb].refnw; ncola++; } else aislado=FALSE; } } if(aislado) { //es una aislada o grupo de aisladas, //deja apuntada a una nw la de distancia menor dmin=MAYUSCULO; iambmin=-1; for(j=0;jn_amb; j++) { if(!(ambs_flgs[j] & FLG_TEMP)) continue; for(k=0;kn_amb].inw_old) continue;//no debería if(inww[j+k*olv_limp->n_amb].inw_old->dminn_amb; dmin=inww[j+k*olv_limp->n_amb].inw_old->dmin; } } } if(dmin=0) { //reapunta a la inw old memcpy(&inww[iambmin],inww[iambmin].inw_old,sizeof(Info_inw_dmin)); free(inww[iambmin].inw_old); inww[iambmin].inw_old=NULL; //añade el segmento de unión add_uniones_obj(iambmin%olv_limp->n_amb); } } //todos los estudiados, que son los del flag temporal, los pone como vistos for(j=0;jn_amb; j++) { if(ambs_flgs[j] & FLG_TEMP) { ambs_flgs[j] = ambs_flgs[j] & ~FLG_TEMP; ambs_flgs[j] = ambs_flgs[j] | FLG_VISTO; //le quita el flag temporal y le pone el de visto } } } free(ambs_flgs); free(ambs_cola); } //************************************************************************************* /** * Comprueba en 'inww' si 'daux' es menor que las almacenadas. * Devuelve la posición del array inww donde tiene que ir o -1 si no es menor * y vacía dicha posición, moviendo las demás, para que el siguiente guarde ahí lo que toca */ int Colv_limp_thr::is_dmin(double daux, Info_inw_dmin *inww) { int i=-1,k; if(!inww) return i; for(i=0; i=i; k--) { memcpy(&inww[k+1], &inww[k],sizeof(Info_inw_dmin)); } break; } } if(i>=OLV_LIMP_N_DMIN_NW) i=-1; return i; } //************************************************************************************* /** * Devuelve la ent de la nw que esté más cerca del ámbito iamb, a la que se le asigna */ BOOL Colv_limp_thr::busca_inw_dmin_ejes(int i_amb) { CartoBaseInfoEntity ientnw, ientamb; int refamb, refenw,inw,z,npts,k; //se recorre las nw buscando el mismo oid ientamb=olv_limp->carto.getEntity(i_amb); refamb=ientamb.entity()->ref; npts=ientamb.getNumberPtos(); //////////////////////////////////////////////////////////////////////// //Bucle por cada carretera de la nw //empiezan donde acaban los ámbitos, y terminan en namb+nnw for(inw=olv_limp->n_amb; inwn_amb+olv_limp->n_nw && !pirate; inw++) { ientnw=olv_limp->carto.getEntity(inw); refenw=ientnw.entity()->ref; if(!(olv_limp->iaso[refenw].flgs & OLV_LIMP_FLG_NW)) continue; //no debería, pero por si acaso if(olv_limp->iaso[refenw].oid==olv_limp->iaso[refamb].oid) break; } if(inw>=olv_limp->n_amb+olv_limp->n_nw || pirate) return FALSE; //ha encontrado la nw, la pone en inww //para el punto inicial y final, o solo una vez si es puntual for(k=0; k<2; k++) { z=i_amb+k*olv_limp->n_amb; olv_limp->inww_amb[z].reset(); olv_limp->inww_amb[z].refnw=refenw; olv_limp->inww_amb[z].dmin=0; olv_limp->inww_amb[z].ip=k*(npts-2); olv_limp->inww_amb[z].lamb=(float)k; memcpy(olv_limp->inww_amb[z].pt,ientamb.getPto(k*(npts-1)),3*sizeof(double)); //copia info de qué amb y qué punto ini o fin es, para poder recuperar cuando está ordenador por inw olv_limp->inww_amb[z].refamb=refamb; olv_limp->inww_amb[z].alpha=(float)(z); } return TRUE; } //************************************************************************************* /** * Devuelve la distancia de un ámbito 'i_amb' a la carretera más cercana, * y rellena la info de dicha carretera en inww_amb. * KK indica el tipo de ámbito, si es 1 es puntual, sólo se calcula una distancia a la carretera, * si es 2, es lineal, se calculan la distancia al extremo inicial y al final */ BOOL Colv_limp_thr::busca_inw_dmin(int i_amb) { Info_inw_dmin inwaux, inww[OLV_LIMP_N_DMIN_NW*2]; //Almacena las N mejores carreteras del punto inicial y las N del punto final CartoLine prime_ptos_i, prime_ptos_f, prime_ptos, ptos_aux; double lon, disptos, daux, alphamin[2], desv,lamb; int i, inw, refenw,k,i_inww,j,jmin[2],i_nw,KK,refamb,ip; CartoBaseInfoEntity ientnw, ientamb; double pt_ang[2][3], *p0, *p1, prod, mod1, mod2; //almacena dos puntos para calcular el vector con el que forma el ángulo el ámbito //////////////////////////// //esto se hace porque se sabe que son siempre 2 puntos, y así no se pide memoria //dinámica en el garray ptos_aux.pts.n = 2; ptos_aux.pts.ptr =pt_ang; //////////////////////////// ientamb=olv_limp->carto.getEntity(i_amb); refamb=ientamb.entity()->ref; KK=olv_limp->tipo_ambit; //inicializa array local para almacenamiento de las tres carreteras más cercanas memset(inww,0,sizeof(Info_inw_dmin)*OLV_LIMP_N_DMIN_NW*2); for(i=0; in_amb; inwn_amb+olv_limp->n_nw && !pirate; inw++) { ientnw=olv_limp->carto.getEntity(inw); refenw=ientnw.entity()->ref; if(!(olv_limp->iaso[refenw].flgs & OLV_LIMP_FLG_NW)) continue; //no debería, pero por si acaso //lo hace para punto inicial y final si es lineal, o solo una vez si es puntual for(k=0; kpts,&ip, &lamb); } inwaux.ip=(short)ip; inwaux.lamb=(float)lamb; i_inww=is_dmin(daux,&inww[k*OLV_LIMP_N_DMIN_NW]); if(i_inww>=0) { //Dist ptos-recta. Si dist mayor que la mínima guardada, descarta. // Si todas dist similares y menores que una dada, se guarda //inw->linea de la nw inww[i_inww+k*OLV_LIMP_N_DMIN_NW].dmin=(float)daux; inww[i_inww+k*OLV_LIMP_N_DMIN_NW].refnw=inwaux.refnw; inww[i_inww+k*OLV_LIMP_N_DMIN_NW].ip = inwaux.ip; inww[i_inww+k*OLV_LIMP_N_DMIN_NW].lamb=inwaux.lamb; inww[i_inww+k*OLV_LIMP_N_DMIN_NW].pt[0]=inww[i_inww+k*OLV_LIMP_N_DMIN_NW].pt[1]= inww[i_inww+k*OLV_LIMP_N_DMIN_NW].pt[2]=0; } } } //////////////////////////////////////////////////////////////////////// //coger de los tres de inww el que del punto ip de nw al extremo de amb forme el ángulo //cuya diferencia con pi/2 sea menor (en el caso lineal) //y ponerlo en inww_amb[i-olv_limp->n_ini_amb] jmin[0]=jmin[1]=0; alphamin[0]=alphamin[1]=MAYUSCULO; for(j=0;j=OLV_LIMP_AMB_NW_NODEF)) //por si acaso continue; ientnw=olv_limp->carto.getRef(i_nw); //calcula el punto del inw donde se da el mínimo p0=ientnw.getPto(inww[j+k*OLV_LIMP_N_DMIN_NW].ip); p1=ientnw.getPto(inww[j+k*OLV_LIMP_N_DMIN_NW].ip+1); inww[j+k*OLV_LIMP_N_DMIN_NW].pt[2]=0; inww[j+k*OLV_LIMP_N_DMIN_NW].pt[0]=p0[0]+(p1[0]-p0[0])*inww[j+k*OLV_LIMP_N_DMIN_NW].lamb; inww[j+k*OLV_LIMP_N_DMIN_NW].pt[1]=p0[1]+(p1[1]-p0[1])*inww[j+k*OLV_LIMP_N_DMIN_NW].lamb; //solo para tipo lineal, elige el de distancia menor y que el ángulo que forma el ámbito con //el punto más cercano de la nw sea el más ortogonal if(KK==OLV_AMB_LIN) { if(k==0) prime_ptos = prime_ptos_i; else prime_ptos = prime_ptos_f; //el ángulo se calcula entre el extremo del ámbito con el vector que forman dicho extremo del //ámbito con el punto del inw donde se da el mínimo pt_ang[0][0] = prime_ptos.getPto(0)[0]; pt_ang[0][1] = prime_ptos.getPto(0)[1]; pt_ang[0][2] = prime_ptos.getPto(0)[2]; pt_ang[1][0] = inww[j+k*OLV_LIMP_N_DMIN_NW].pt[0]; pt_ang[1][1] = inww[j+k*OLV_LIMP_N_DMIN_NW].pt[1]; pt_ang[1][2] = inww[j+k*OLV_LIMP_N_DMIN_NW].pt[2]; prod=GeometryFunction::ProdEscalar(&prime_ptos,&ptos_aux); mod1=GeometryFunction::Dist2d(prime_ptos.getPto(0), prime_ptos.getPto(1)); mod2=GeometryFunction::Dist2d(pt_ang[0],pt_ang[1]); inww[j+k*OLV_LIMP_N_DMIN_NW].alpha=(float)fabs(prod/(mod1*mod2)); } } } if(pirate) goto fin; if(KK==OLV_AMB_LIN) { //únicamente si el segundo más cercano (el de la pos '1') tiene alpha menor, y una distancia no mucho mayor //lo coge, //si no, se queda el más cercano for(k=0; kres_circ!=OLV_RES_NO) { //si hay restricciones de circulación, y se va a coger como dmin una carretera peatonal, coge la siguiente de dmin for(k=0; kiaso[inww[k*OLV_LIMP_N_DMIN_NW].refnw].flgs & OLV_LIMP_FLG_CIRC_NONE) && !(olv_limp->iaso[inww[1+k*OLV_LIMP_N_DMIN_NW].refnw].flgs & OLV_LIMP_FLG_CIRC_NONE)) jmin[k]=1; } } //copia el mínimo que ha encontrado //para el punto inicial y final, o solo una vez si es puntual for(k=0; kinww_amb[i_amb+k*olv_limp->n_amb],&inww[jmin[k]+k*OLV_LIMP_N_DMIN_NW],sizeof(Info_inw_dmin)); //copia info de qué amb y qué punto ini o fin es, para poder recuperar cuando está ordenador por inw olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].refamb=refamb; olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].alpha=(float)(i_amb+k*olv_limp->n_amb); } fin: prime_ptos.pts.ptr = NULL; ptos_aux.pts.ptr = NULL; return TRUE; } //************************************************************************************* /** * Dado un ámbito 'i_amb' (ya relativo al n_ini_amb) de un total de n_amb, * de 'npt_amb' puntos almacenados en 'pt_amb', * añade al 'ob' las uniones del mismo con la carretera 'pt_nw' * de los dos extremos si es lineal o uno si es puntual, indicado por 'KK' */ void Colv_limp_thr::add_uniones_obj(int i_amb) { double ptos[2][3]; int refamb,nptos,KK, refnw,npt_amb; CartoBaseInfoEntity ientamb,ientnw,ientseg; CartoLine ptos_aux; INT64 ff; Info_aso2 info_aux; BOOL ya=TRUE; Info_inw_dmin *inww; //////////////////////////// //esto se hace porque se sabe que son siempre 2 puntos, y así no se pide memoria //dinámica en el garray ptos_aux.pts.n = 2; ptos_aux.pts.ptr = ptos; //////////////////////////// ientamb=olv_limp->carto.getEntity(i_amb); refamb=ientamb.entity()->ref; KK=olv_limp->tipo_ambit; nptos=2; //siempre añade segmentos //poner el flag de segmento, si es eje, refe2... si es lin o pun, si es fin... if(KK==OLV_AMB_LIN) ff=OLV_LIMP_FLG_SEG_LIN; else ff=OLV_LIMP_FLG_SEG_PUN; if(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_EJE) ff|=OLV_LIMP_FLG_EJE_SEG; ////////////////////////// for(int k=0; kinww_amb[i_amb+k*olv_limp->n_amb]; ya=TRUE; do { //apunta al nw más cercano del ámbito actual que se acaba de encontrar refnw=inww->refnw; if(refnw<0 || refnw>=(olv_limp->n_nw+olv_limp->n_amb) || (refnw==i_amb)) //por si acaso continue; ientnw = olv_limp->carto.getRef(refnw); //apunta el array de puntos al ámbito if(KK==OLV_AMB_LIN)//para tipo lineal, obtiene los primeros puntos de los dos extremos { npt_amb = ientamb.getNumberPtos(); } else if(KK==OLV_AMB_PUN) //para tipo puntual, es un único punto { npt_amb = 1; } if(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_AMB) ff |= OLV_LIMP_FLG_DER | OLV_LIMP_FLG_SEG_AMB; else if(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_NW) { if((GeometryFunction::IsDer(&ientnw, ientamb.getPto((npt_amb-1)*k),inww->ip, inww->ip+1))) { if(!(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_CIRC_TF)) { ff |= OLV_LIMP_FLG_DER; //FT o both olv_limp->iaso[refamb].flgs |= OLV_LIMP_FLG_DER; } } else if(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_CIRC_TF) { ff |= OLV_LIMP_FLG_DER; //TF olv_limp->iaso[refamb].flgs |= OLV_LIMP_FLG_DER; } } if(k==OLV_AMB_LIN-1) ff|=OLV_LIMP_FLG_FIN; //rellena el segmento //el primer punto es el de la carretera más cercano al ámbito memcpy(ptos[0],inww->pt,3*sizeof(double)); //el segundo punto es el propio del ámbito (inicio y final si es lineal) memcpy(ptos[1],ientamb.getPto((npt_amb-1)*k),3*sizeof(double)); //lo añade al carto olv_limp->carto.add(ptos_aux); ientseg=olv_limp->carto.getEntity(olv_limp->carto.getNumberEntities()-1); //Añade la info aso info_aux.reset(); info_aux.flgs=ff; info_aux.refe=ientseg.entity()->ref; info_aux.refe2=ientamb.entity()->ref; olv_limp->iaso[info_aux.refe]=info_aux; if(inww->inw_old)//ojo { if(inww->inw_old->dmininw_old;//añade las uniones a la nw y a los cercanos siempre! ya=FALSE; } else ya=TRUE; } else ya=TRUE; } while (!ya); } ptos_aux.pts.ptr = NULL; } //************************************************************************************* /** * Comprueba si el segmento corta a otro ámbito (en tratamientos lineales) * si lo corta, apunta el primer punto del segmento al punto extremo más cercano * de dicho ámbito al ámbito ppal */ void Colv_limp_thr::compr_cortes_amb() { olvlog(LOG_TODO,"olv_limp_t","Comprobando cortes entre uniones y ámbitos"); pon_mi_progre(OLV_TAREA_COST_AMB, 0); pon_mi_msg("Comprobando cortes entre uniones y ámbitos"); err_str[0]=0; //lanza los threads lanza_subthrs(OLV_LIMP_EV_COMPCORT_SUB,1); } //************************************************************************************* /** * Función de los subthreads */ void Colv_limp_thr::compr_cortes_amb_sub(int ithr) { int na_ini,na_fin,na_desp,na; int KK, seg; Param_olv_limp_thr pp; CartoBaseInfoEntity ient_na, ient_i, ient_ia; int ref_na, ref_i, ref_ia, isg,nent; int iamb2,npt_amb2,ip,h; double dist,lamb,*pt_amb2,lambs,distseg; //////////////// pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso KK=olv_limp->tipo_ambit; na_desp = (int)ceil(1.0*(olv_limp->n_amb)/n_subthr); na_ini= min(ithr*na_desp, olv_limp->n_amb); na_fin = min((ithr+1)*na_desp,olv_limp->n_amb); //////////////// olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Ambs %04d a %04d", ithr,na_ini, na_fin); seg = GetTickCount(); ///////////////////////////////////// //Bucle por cada ámbito de los que le tocan a este thread ///////////////////////////////////// na=na_ini; nent=olv_limp->carto.getNumberEntities(); ///////////////////////////////////// for(na=na_ini;nacarto.get(na); ref_na=ient_na.entity()->ref; //revisa si la unión de este ámbito con la carretera interseca con otro ámbito for(isg=olv_limp->n_amb+olv_limp->n_nw;isgcarto.get(isg); if(ient_i.entity()->type!=CartoBaseTypes::Line) continue; ref_i=ient_i.entity()->ref; if(!(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_SEG_LIN) || olv_limp->iaso[ref_i].refe2!=ref_na || (olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_SEG_AMB)) continue; //ha encontrado el segmento inicial del ámbito, comprueba si corta con algún otro ámbito //recorre de nuevo los ámbitos, esta vez todos for(iamb2=0;iamb2n_amb;iamb2++) { if(iamb2==na) continue; ient_ia=olv_limp->carto.get(iamb2); ref_ia=ient_ia.entity()->ref; if(olv_limp->iaso[ref_ia].refe2==ref_na || olv_limp->iaso[ref_na].refe2==ref_ia) continue; dist=ient_ia.DplineSeg(ient_i.getPto(0), ient_i.getPto(1),&ip, &lamb,&lambs); if(dist>=OLV_DIF_MAX_MISMA_COOR || (lambs<=0.1) || (lambs>=0.9)) continue;//no intersecan //intersecan //apunta el primer ámbito al extremo más cercano del otro ámbito //mira cuál es el extremo más cercano npt_amb2 = ient_ia.getNumberPtos(); //pt_amb2=ient_ia.PtInLine(ip, lamb,pt_aux); //renombra pt_amb2 al extremo al que esta mas cerca if((ip+lamb)>=((npt_amb2-1)/2)) { //extremo final h=1; } else { //extremo inicial h=0; } pt_amb2=ient_ia.getPto((npt_amb2-1)*h); //calcula distancia del ámbito a ientamb2 dist=GeometryFunction::Dist2d(ient_i.getPto(1),pt_amb2);//el segundo punto de la unión es el punto del ámbito distseg=ient_i.getLong();//la longitud del segmento que lo unía con la carretera if(dist<1.5*distseg && distencola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); } } olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin comprobación cortes entre uniones y ambs, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); thr_padre->encola(OLV_LIMP_EV_COMPCORT_FIN,NULL,FALSE); } //************************************************************************************* /** * Función final */ BOOL Colv_limp_thr::compr_cortes_amb_sub_fin() { //para los threads para_subthrs(); return TRUE; } //************************************************************************************* /** * Comprueba, si es ámbito, si la carretera está muy lejos. * Si es que sí, o bien busca otro ámbito más cercano, o lo deja vacío */ void Colv_limp_thr::comprueba_amb_lejos(int i_amb ) { int i,k,h, iaux,is_fin,npt_amb_min, lejos; double dist_aux,dist_aux2,dmin,dmax,longmax; double *pt_amb_min; BOOL ya_ini; BOOL modo_solouno; BOOL modo_unolibre; Info_inw_dmin *inwaux=NULL; int KK,refamb,refamb2,npt_amb,npt_amb2; CartoBaseInfoEntity ientamb,ientamb2; double *pt_amb, *pt_amb2; BOOL guarda_nw_old; /*double lamb, pt_aux[3]; int ip;*/ //////////////////////// KK=olv_limp->tipo_ambit; dmax=OLV_DIST_MAX_AMB_NW;// m de separación max entre peatonal y calle /////////////////////// ientamb=olv_limp->carto.getEntity(i_amb); refamb=ientamb.entity()->ref; npt_amb=ientamb.getNumberPtos(); /////////////////////// ya_ini=FALSE; modo_unolibre=(olv_limp->iaso[refamb].flgs & OLV_LIMP_FLG_AMB_PEAT); //Solo para las peatonales permite dejar un lado sin apuntar modo_solouno=FALSE; lejos=0; longmax=dmax; if(modo_unolibre) longmax=ientamb.getLong(); //Calcula la distancia del principio y del final a la nw for(k=0;kinww_amb[i_amb+k*olv_limp->n_amb].pt); guarda_nw_old=TRUE; //if(dist_aux2n_amb; i++) { if(i==i_amb) continue; ientamb2=olv_limp->carto.getEntity(i); refamb2=ientamb2.entity()->ref; if(olv_limp->iaso[refamb2].flgs & OLV_LIMP_FLG_AMB_NO) continue; if(KK==OLV_AMB_LIN)//para tipo lineal, obtiene los primeros puntos de los dos extremos { npt_amb2 = ientamb2.getNumberPtos(); } else if(KK==OLV_AMB_PUN) //para tipo puntual, es un único punto { npt_amb2 = 1; } for(h=0;h=((npt_amb2-1)/2)) { //extremo final h=1; } else { //extremo inicial h=0; } pt_amb2=ientamb2.getPto((npt_amb2-1)*h); } else if(KK==OLV_AMB_PUN) //para tipo puntual, es un unico punto { npt_amb2 = 1; pt_amb2 = ientamb2.getPto(0); dist_aux=GeometryFunction::Dist2d(pt_amb, pt_amb2); h=0; } if(dist_auxinww_amb[iaux+is_fin*olv_limp->n_amb].refnw==i_amb) && olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old) { //si sí, comprueba cuál de los dos tiene la nw a menos distancia //ese lo apunta a la nw y el otro al ámbito cercano if(olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old->dmin< olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].dmin) { if(olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old->dmininww_amb[iaux+is_fin*olv_limp->n_amb].inw_old; memcpy(&olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb],inwaux,sizeof(Info_inw_dmin)); //libera el old free(olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old); olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old=NULL; } //si es mayor que dmax, el anterior se queda como está, y este pone de ppal al ámbito y no guarda old //indica que no guarde de este el old porque solo va a coger de ppal al ámbito guarda_nw_old=FALSE; } else { //es éste el que está más cerca //al otro le borra el old free(olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old); olv_limp->inww_amb[iaux+is_fin*olv_limp->n_amb].inw_old=NULL; if(olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].dmininww_amb[i_amb+k*olv_limp->n_amb],sizeof(Info_inw_dmin)); olv_limp->inww_amb[i_amb+k*olv_limp->n_amb].inw_old = inwaux; } //copia en la principal la nueva info inwaux=&olv_limp->inww_amb[i_amb+k*olv_limp->n_amb]; //////////////////////////////////////////// inwaux->dmin = (float)dmin; inwaux->refnw = iaux; inwaux->ip = (npt_amb_min-1)*is_fin; inwaux->lamb = 0; memcpy(inwaux->pt,pt_amb_min,3*sizeof(double)); ya_ini=TRUE; } else if((dmin>longmax) && !modo_solouno) { //si está todavía más lejos, lo apunta a su principio lejos|=1<inww_amb[i_amb].refnw = refamb; olv_limp->inww_amb[i_amb].ip =0; memcpy(olv_limp->inww_amb[i_amb].pt,ientamb.getPto(olv_limp->inww_amb[i_amb].ip),3*sizeof(double)); } else if(lejos & (1<<0)) { //si ha dejado sólo el segundo olv_limp->inww_amb[i_amb+olv_limp->n_amb].refnw = refamb; olv_limp->inww_amb[i_amb+olv_limp->n_amb].ip = npt_amb-1; memcpy(olv_limp->inww_amb[i_amb+olv_limp->n_amb].pt,ientamb.getPto(olv_limp->inww_amb[i_amb+olv_limp->n_amb].ip),3*sizeof(double)); } } //************************************************************************************* /** * Comprueba si hay ámbitos a un lado que se supone deberían estar al otro */ BOOL Colv_limp_thr::comprueba_latelaridad() { int sent,id; BOOL sigue_msg=TRUE; if(olv_limp->res_circlateral<=0) return TRUE; char msg_[OLV_MAX_MSG_PROCE]; char nfile[MAX_PATH]; strcpy_s(nfile,MAX_PATH,olv->paths.path_data); //cambiaext(nfile,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); msg_[0]=0; ///////////////////LATERALIDAD //recorres inww_amb_aux, que está ordenado por inw //solo en puntuales //si res_cirobjt)[inww_amb_aux[i].inw].ia].flgs & OLV_LIMP_FLG_CIRC_FT //fronto mismo sentido que lineal //si lateral==derecha y amb a la izquierda, descarta //amb -> ias[inww_amb_aux[ì].iamb].flgs & OLV_LIMP_FLG_DER //o si lateral==izda y amb a la derecga, descarta for(int ia=0; ian_amb; ia++) { sent=0; if(olv_limp->iaso[olv_limp->inww_amb[ia].refnw].flgs & OLV_LIMP_FLG_CIRC_FT ) sent++; if(olv_limp->iaso[olv_limp->inww_amb[ia].refnw].flgs & OLV_LIMP_FLG_CIRC_TF ) sent++; if(sent!=1) continue; //comprueba lateralidad if(olv_limp->iaso[olv_limp->inww_amb[ia].refamb].flgs & OLV_LIMP_FLG_DER)//ambito a la derecha { if(olv_limp->lateral==1) //lateralidad derecha continue; } else//ambito a la izquierda { if(olv_limp->lateral==2) //lateralidad izquierda continue; } //lee el objectid del ámbito id=olv_limp->iaso[olv_limp->inww_amb[ia].refamb].oid; olvlog(LOG_TODO,"olv_limp_t","Ámbito %ld lateralidad errónea",olv_limp->iaso[olv_limp->inww_amb[ia].refamb].oid); //imprime if(msg_[0]==0) sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Encontrados contenedores con lateralidad errónea: "); if(sigue_msg) sprintf_s(msg_,OLV_MAX_MSG_PROCE,"%s %ld,",msg_,id); if(sigue_msg && strlen(msg_)+10>=OLV_MAX_MSG_PROCE) sigue_msg=FALSE;//para que no se pase del largo } if(!sigue_msg && ((strlen(msg_)+5)tipo_ambit; mal=FALSE; nwcp.idPropsP=0; ///////////////// ///////////////// olvlog(LOG_TODO,"olv_limp_t","Generando topología con los segmentos de unión"); pon_mi_progre(OLV_TAREA_TOPO_NW, 0); pon_mi_msg(""); err_str[0]=0; int ent1=olv_limp->carto.getNumberEntities(); //inicializa la matriz auxiliar para ordenación inww_amb_aux = (Info_inw_dmin *)malloc(olv_limp->n_amb*KK*sizeof(Info_inw_dmin)); if(!inww_amb_aux) { pon_mi_msg("Error, sin memoria para matriz de índices\nde ámbitos a carreteras"); return FALSE; } memcpy(inww_amb_aux,olv_limp->inww_amb,olv_limp->n_amb*KK*sizeof(Info_inw_dmin)); ////////////////////////////////////////////////// //ordena la matriz de info de inw, va de punto más cercano //al inicio del inw inicial al más lejano, y aumentando en inw //dentro del mismo inw, ordena por ip y a igual ip, por lamb qsort(inww_amb_aux,olv_limp->n_amb*KK,sizeof(Info_inw_dmin),Colv_limp_thr::compara_inww_amb); olvlog(LOG_TODO,"olv_limp_t","Generando topología: Matriz de info de inw dmin ordenada"); ////////////////////// //mira a ver si tiene que replicar calles de doble sentido if(!replica_doble_sent(inww_amb_aux)) { pon_mi_msg("Errores al replicar doble sentido"); return FALSE; } //hay que volver a ordenar por si se ha modificado algo al replicar qsort(inww_amb_aux,olv_limp->n_amb*KK,sizeof(Info_inw_dmin),Colv_limp_thr::compara_inww_amb); //////////////////// if(KK<2)//en recogida, se mira si hay que comprobar la lateralidad comprueba_latelaridad(); /////////////////////////////////////////////////////////////////////// //Bucle por cada item del array inww_amb, para ir troceando las carreteras que cortan ia=0; while(ian_amb*KK && !pirate) { /////////////////////////////// ia_aux=ia; refnw=inww_amb_aux[ia_aux].refnw; if(olv_limp->iaso[inww_amb_aux[ia_aux].refamb].flgs & OLV_LIMP_FLG_AMB_NO) { ia++; continue; } if(!(olv_limp->iaso[refnw].flgs & OLV_LIMP_FLG_NW)) //es que se ha reapuntado a otro ámbito por ser peatonal lejana { ia++; continue; } ientnw=olv_limp->carto.getRef(refnw); npt_nw=ientnw.getNumberPtos(); memcpy(&info_aux,&olv_limp->iaso[refnw],sizeof(Info_aso2)); iat=ia; nt=1; //primero cuenta los tramos de esa inwi, nt while((ian_amb*KK) && (inww_amb_aux[ia].refnw==refnw)) { ia++; nt++; } if(nt<2) //tiene que haber siempre mínimo 2 tramos, ya que en todos los inw de este array hay algún ámbito asignado { olvlog(LOG_TODO,"olv_limp_t","Gen. Topo. Inw %03d mal, se obtienen %ld tramos, no suficientes",refnw,nt); mal=TRUE; ia++; continue; } //ya se saben los tramos, se va troceando la carretera ia=iat; iat=0; inww_amb_aux[ia].flgs=0; while(iat0 && inww_amb_aux[ia-1].flgs>1) olv_limp->inww_amb[(int)inww_amb_aux[ia-1].alpha].refnw=info_aux.refe; //recorre la carretera inwi y la parte en trozos acorde a los ámbitos if(iat==0)//hace el primer tramo, del extremo inicial al primer ámbito { npt_nw_aux=inww_amb_aux[ia].ip+2; if(Colv_geom::pto_equals(ientnw.getPto(0), inww_amb_aux[ia].pt)) { //no se hace tramo porque está unido por el extremo iat++; ia++; if(nt==2) { iat++;//si solo eran dos tramos, pasa ia++; } continue; } //los primeros puntos son los de la carretera hasta el ámbito for(pp=0;ppcarto.add(ptos_aux); info_aux.refe=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1).entity()->ref; if(olv_limp->iaso[refnw].inf_n.nomb) { info_aux.inf_n.nomb = (char*)malloc(strlen(olv_limp->iaso[refnw].inf_n.nomb)+1); strcpy(info_aux.inf_n.nomb,olv_limp->iaso[refnw].inf_n.nomb); } olv_limp->iaso[info_aux.refe]=info_aux; iat++; ia++; } if((ia%100==0) || (ia==(olv_limp->n_amb*KK))) { olvlog(LOG_TODO,"olv_limp_t","Generando topología, %ld de %ld",ia,olv_limp->n_amb*KK); //avisa de progreso pon_mi_progre(OLV_TAREA_TOPO_NW, (int) ((OliviaDef::GeneralDef::ProgrMax* 1.0*(ia)/(olv_limp->n_amb*KK)))); } ia--; //decrementa para cuando se ha pasado } info_aux.inf_n.nomb = NULL; if(mal) { pon_mi_msg("Errores en el análisis topológico"); } if(mal || pirate) { if(inww_amb_aux) free(inww_amb_aux); return FALSE; } int ia_old; ia=ia_old=0; while(ian_amb*KK) { refnw=inww_amb_aux[ia].refnw; if(olv_limp->iaso[inww_amb_aux[ia].refamb].flgs & OLV_LIMP_FLG_AMB_NO) { ia++; continue; } if((refnw<0) || (refnwn_amb) || (inww_amb_aux[ia].flgs<2)) //si al final no ha hecho tramos { ia++; continue; } //marca para borrar calle olv_limp->carto.removeRef(refnw); //avanza hasta el siguiente inwi while((ian_amb*KK) && (inww_amb_aux[ia].refnw==refnw)) { ia++; } } //hace limpieza de la carto olv_limp->carto.FastClear(); if(inww_amb_aux) free(inww_amb_aux); if(!pon_nodos_planta(olv_limp->coor_instal)) { pon_mi_msg("Error, No se ha podido incluir planta en red"); return FALSE; } //hace limpieza de la carto, ya que ha terminado de hacer topología o añadir cosas olv_limp->carto.FastClear(); //olv_limp->carto.linesExportShp("C:\\Proyectos\\Olivia\\Instal\\topo.shp"); return TRUE; } //************************************************************************************* /** * Compara las estructuras inww_amb. Las ordena por inw, a mismo inw por ip, y a mismo ip por lamb */ int Colv_limp_thr::compara_inww_amb (const void * a, const void * b) { //si arefnw - ((Info_inw_dmin*) b)->refnw; if(r==0) { //a mismo inw, es menor el de menor ip r=((Info_inw_dmin*) a)->ip - ((Info_inw_dmin*) b)->ip; if(r==0) { //a mismo ip, es menor el de menor lamb dd=((Info_inw_dmin*) a)->lamb - ((Info_inw_dmin*) b)->lamb; if(dd<0) r=-1; else if(dd>0) r=1; else r=0; } } return r; } //************************************************************************************* /** * Añade a la red de conjunciones en qué conjunción está la planta y la instalación */ BOOL Colv_limp_thr::pon_nodos_planta(double pt[3]) { int i, nent, refent,ip; double dmin,d,lamb,pt_proy_nw[3],*pt_ip,*pt_ip1; CartoBaseInfoEntity ientnw; CartoLine lines[2]; Info_inw_dmin inww; Info_aso2 info_aux; if((pt[0]==0) && (pt[1]==0)) return TRUE;//no hay instalación, no se pone //////////////////////////////////////////////////////////////////////// //Bucle por cada carretera de la nw dmin=DBL_MAX; nent=olv_limp->carto.getNumberEntities(); inww.reset(); for(i=0; icarto.get(i).entity()->type!=CartoBaseTypes::Line) continue; refent=olv_limp->carto.get(i).entity()->ref; if(!(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_NW)) continue; ientnw=olv_limp->carto.get(i); //calcula la distancia al punto de la instalación d = ientnw.DisPtoLine(pt,&ip,&lamb); if(d=DBL_MAX) return FALSE; ///////////////////////////////////////////////// //ya tiene el inw de la distancia mínima //apunta al que ha encontrado mínimo ientnw = olv_limp->carto.getRef(inww.refnw); //calcula el punto del inw donde se da el mínimo pt_ip=ientnw.getPto(inww.ip); pt_ip1=ientnw.getPto(inww.ip+1); pt_proy_nw[2]=0; for(i=0;i<2;i++) pt_proy_nw[i]=pt_ip[i]+(pt_ip1[i]-pt_ip[i])*inww.lamb; ///////////////////////////////////////////////// //sustituye las coords por el punto proyectado en la nw memcpy(pt,pt_proy_nw,3*sizeof(double)); ///////////////////////////////////////////////// //hace dos tramos if(!ientnw.DivLine(&lines[0],&lines[1],inww.ip,inww.lamb)) return FALSE; //añade los tramos, les pone la misma info asociada que la carretera original info_aux.reset(); memcpy(&info_aux,&olv_limp->iaso[inww.refnw],sizeof(Info_aso2)); for(i=0;i<2;i++) { if(lines[i].getNumberPtos()<2) continue; olv_limp->carto.add(lines[i]); info_aux.refe=olv_limp->carto.get(olv_limp->carto.getNumberEntities()-1).entity()->ref; if(olv_limp->iaso[inww.refnw].inf_n.nomb) { info_aux.inf_n.nomb = (char*)malloc(strlen(olv_limp->iaso[inww.refnw].inf_n.nomb)+1); strcpy(info_aux.inf_n.nomb,olv_limp->iaso[inww.refnw].inf_n.nomb); } olv_limp->iaso[info_aux.refe]=info_aux; } olv_limp->carto.removeRef(inww.refnw); //olv_limp->carto.clear(); //se hace después return TRUE; } //************************************************************************************* /** * Apunta en qué nodos está la planta y la instalación */ BOOL Colv_limp_thr::busca_conjs_planta(double pt[3], int *nod) { int ic; BOOL mal=FALSE; if((pt[0]==0) && (pt[1]==0)) return TRUE;//no hay instalación, no se pone //busca ese punto en la lista de conjunciones //busca la conjunción en la lista //lo hace para los dos extremos de la línea for(ic=0; icconjs.n;ic++) { if((Colv_geom::pto_equals(pt,olv_limp->conjs.coor[ic]))) break; } if(ic==olv_limp->conjs.n) { return FALSE; } *nod=ic; return TRUE; } //************************************************************************************* /** * Lanza sub-threads */ void Colv_limp_thr::lanza_subthrs(int tar, int nthr_def/*=-1*/) { char nomb[32]; Param_olv_limp_thr pp; int nn; if((nthr_def>0) && (nthr_defthr_padre=this; subthrs[i]->n_subthr = nn; subthrs[i]->prog_subthr = 0; subthrs[i]->pirate=FALSE; subthrs[i]->inicia(OLV_MILIS_COLA,&cola_proc,-1,nomb); subthrs[i]->encola(tar,&pp,FALSE); } //fuerza fin para que avance olivia for(int i=nn;iprog_subthr = 0; } for(int i=0;ipirate=pirate; subthrs[i]->termina(); } } } //************************************************************************************* /** * Rellena la matriz de costes entre todas las conjunciones */ BOOL Colv_limp_thr::calcula_cost_conj() { int i; //////////////// olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de costes entre conjunciones"); pon_mi_progre(OLV_TAREA_COST_AMB, 0); pon_mi_msg("Rellenando matriz de costes entre nodos"); err_str[0]=0; //calcula el número de nodos de la red //que es el número de intersecciones de la red navegable, incluyendo el número de ámbitos x2 porque //aparecen el punto del ámbito y el proyectado en la carretera más próxima (y x2 si son lineales) olvlog(LOG_TODO,"olv_limp_t","Comienza a buscar conjunciones"); if(!busca_conjs()) { pon_mi_msg("Error, sin memoria para matriz de conjunciones en busca_conjs"); return FALSE; } //***************************************************************** //log_debug /*CartoBaseInfoEntity ient; int refent; for(int i=0;in_amb;i++) { refent=i; ient=olv_limp->carto.getRef(refent); olvlog(LOG_TODO,"olv_limp_t","refent %04d flgs 0x%x -----------------------", refent, olv_limp->iaso[refent].flgs); olvlog(LOG_TODO,"olv_limp_t","inod 0 %03d 1 %03d",olv_limp->iaso[refent].inod[0],olv_limp->iaso[refent].inod[1]); olvlog(LOG_TODO,"olv_limp_t","refe2 %04d",olv_limp->iaso[refent].refe2); olvlog(LOG_TODO,"olv_limp_t","refe_nw 0 %04d 1 %04d",olv_limp->iaso[olv_limp->inww_amb[refent].refnw].oid, olv_limp->iaso[olv_limp->inww_amb[refent+olv_limp->n_amb].refnw].oid); olvlog(LOG_TODO,"olv_limp_t","refe_nw inod 0 %03d 1 %03d",olv_limp->iaso[olv_limp->inww_amb[refent].refnw].inod[0], olv_limp->iaso[olv_limp->inww_amb[refent+olv_limp->n_amb].refnw].inod[1]); }*/ //***************************************************************** pon_mi_msg("Rellenando matriz de costes entre nodos. %ld nodos por calcular", olv_limp->conjs.n); //pide memoria para el array de distancias entre conjunciones ///mira a ver con cuántos nvect puede calcular la matriz CoptiMemo oo; int nvect = oo.calc_nvect_master(olv_limp->conjs.n); if(nvect<0) { pon_mi_msg("Error, sin memoria para matriz de conjunciones en cálculo de nvect"); return FALSE; } olvlog(LOG_TODO,"olv_limp_t","Se va a ejecutar con nvect=%ld de %ld",nvect,olv_limp->conjs.n); olv_limp->cost_conj.clear(); olv_limp->tip_conj.clear(); olv_limp->cost_conj.inicializa(olv_limp->conjs.n,n_subthr,nvect); olv_limp->tip_conj.inicializa(olv_limp->conjs.n,n_subthr,nvect); //si solo le llega una calle a una conjunción, y es de sentido único, le pone doble sentido for(i=0;iconjs.n;i++) { if(olv_limp->conjs.inc[i].n==1) { if(olv_limp->iaso[olv_limp->conjs.inc[i].refnw0].flgs & (OLV_LIMP_FLG_CIRC_FT | OLV_LIMP_FLG_CIRC_TF)) olv_limp->iaso[olv_limp->conjs.inc[i].refnw0].flgs &= ~OLV_LIMP_FLG_CIRC_FT & ~OLV_LIMP_FLG_CIRC_TF; } } //lanza los threads lanza_subthrs(OLV_LIMP_EV_COST_CONJ_SUB); return TRUE; } //************************************************************************************* /** * Comprueba la memoria para las conjunciones */ BOOL Colv_limp_thr::add_conj(Info_conjs *conjs, double coor[3]) { if(!cuida_memo_conj(conjs)) return FALSE; memcpy(conjs->coor[conjs->n],coor,3*sizeof(double)); conjs->n++; return TRUE; } //************************************************************************************* /** * Comprueba la memoria para las conjunciones */ BOOL Colv_limp_thr::cuida_memo_conj(Info_conjs *conjs) { double (*coor2)[3]; Info_conjs_inw *inc2; if((conjs->n+1)>conjs->m) { conjs->m+=OLV_LIMP_M_CONJ; //primero las coordenadas coor2 = (double (*)[3])realloc(conjs->coor,conjs->m*3*sizeof(double)); if(!coor2) { free(conjs->coor); return FALSE; } conjs->coor=coor2; memset(&conjs->coor[conjs->m-OLV_LIMP_M_CONJ],0,OLV_LIMP_M_CONJ*3*sizeof(double)); //primero las incidencias inc2 = (Info_conjs_inw *)realloc(conjs->inc,conjs->m*sizeof(Info_conjs_inw)); if(!inc2) { free(conjs->inc); return FALSE; } conjs->inc=inc2; //inicializa for(int i=conjs->m-OLV_LIMP_M_CONJ;im;i++) { conjs->inc[i].n=conjs->inc[i].refnw0=-1; } } return TRUE; } //************************************************************************************* /** * Rellena la matriz de conjunciones entre toda la red, navegable y ámbitos * y la info de las conjunciones se rellena en 'conjs' */ BOOL Colv_limp_thr::busca_conjs() { int io, refent, nent,i,k,npts,ic, ics[2], refe2,sum; CartoBaseInfoEntity ient; double *pto; BOOL modo_ejes, mal; mal=modo_ejes=FALSE; if((olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) || (olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) modo_ejes=TRUE; //bucle por cada entidad de la carto //si es modos de ámbitos normales, lineales o puntuales, se va de inicio a final del carto, en orden //y se van buscando las conjs de los ámbitos, los nw, y los segmentos //si es un modo en el que los ámbitos son ejes, se va al revés, añadiendo primero las conjunciones de //los segmentos y la nw, y por último las de los ejes. Se hace para que en el siguiente paso, al buscar, //aparezca primero la conjunción de la carretera, porque es de la que no se tiene constancia ic_ini/ic_fin io=0; nent=olv_limp->carto.getNumberEntities(); if(modo_ejes) { i=nent; sum=-1; } else { i=-1; sum=1; } for(io=0;iocarto.get(i).entity()->type!=CartoBaseTypes::Line) continue; ient=olv_limp->carto.get(i); refent=ient.entity()->ref; npts=ient.getNumberPtos(); if((olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_PEAT_SEG) || (olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_EJE_SEG)) continue; for(k=0; k<2; k++) { pto = ient.getPto(k*(npts-1)); if((olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_PEAT_REP) || (olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_EJE)) { //en estos casos replica las conjunciones //llega la segunda vez ic=olv_limp->conjs.n; if(!add_conj(&olv_limp->conjs, pto)) { mal=TRUE; break; } } else { //busca la conjunción en la lista //lo hace para los dos extremos de la línea for(ic=0; icconjs.n;ic++) { if((Colv_geom::pto_equals(pto,olv_limp->conjs.coor[ic]))) break; } if(ic==olv_limp->conjs.n) { //no lo ha encontrado, lo añade if(!add_conj(&olv_limp->conjs,pto)) { mal=TRUE; break; } } } ics[k]=ic; //si es carretera, le pone a la conjunción que llega una al menos //if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_NW) { if(olv_limp->conjs.inc[ic].n<0) { olv_limp->conjs.inc[ic].n=1; olv_limp->conjs.inc[ic].refnw0=refent; } else olv_limp->conjs.inc[ic].n++; } } //guarda las conjunciones en la iaso for(k=0; k<2; k++) { olv_limp->iaso[refent].inod[k]=ics[k]; } //si es segmento de ámbito puntual, le pone al ámbito la conjunción if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_SEG_PUN) { refe2=olv_limp->iaso[refent].refe2; olv_limp->iaso[refe2].inod[0]=olv_limp->iaso[refe2].inod[1]=ics[1]; } } if(iocarto.getNumberEntities(); int ref1, ref2; for(i=0;icarto.get(i).entity()->type!=CartoBaseTypes::Line) continue; ient=olv_limp->carto.get(i); refent=ient.entity()->ref; npts=ient.getNumberPtos(); if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_PEAT_SEG) { //ref1 es la réplica de la peatonal ref1=olv_limp->iaso[refent].refe; //ref2 es la peatonal original ref2=olv_limp->iaso[refent].refe2; } else if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_EJE_SEG) { //ref1 es el eje original, como ámbito ref1=olv_limp->iaso[refent].refe2; //ref2 es la calle a la que está asignado ref2=olv_limp->inww_amb[ref1].refnw; } else continue; if(olv_limp->iaso[refent].flgs & OLV_LIMP_FLG_FIN) k=1; else k=0; //el primer nodo el del ámbito olv_limp->iaso[refent].inod[0]=olv_limp->iaso[ref1].inod[k]; //el primer nodo el de la réplica olv_limp->iaso[refent].inod[1]=olv_limp->iaso[ref2].inod[k]; } olvlog(LOG_TODO,"olv_limp_t","Encontradas %ld conjunciones en la red navegable",olv_limp->conjs.n); olvlog(LOG_TODO,"olv_limp_t","Comienza a buscar las conjunciones de la planta"); if(!busca_conjs_planta(olv_limp->coor_instal, &olv_limp->nod_instal)) { olvlog(LOG_TODO,"olv_limp_t","No se ha podido encontrar los nodos de la planta"); return FALSE; } olvlog(LOG_TODO,"olv_limp_t","Encontradas las conjunciones de la planta"); return TRUE; } //************************************************************************************* /** * Rellena la matriz de distancias entre todas las conjunciones. * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado */ BOOL Colv_limp_thr::calcula_cost_conj_fin() { //////////////// //para los threads para_subthrs(); //olv_limp->cost_conj.memAjust(); olvlog(LOG_TODO,"olv_limp_t","FIN Matriz de dist entre conjs %ldx%ld", olv_limp->conjs.n,olv_limp->conjs.n); /////////////////////////////// /*if(olv_limp->res_circ==OLV_RES_NO) { //va directo a cost_amb, calcula ahora si va a ser multitask o no //calcula si puede ser multitask o no CoptiMemo oo; olv->modo_multitask=oo.is_multi(olv_limp->conjs.n,n_subthr,sizeof(Djkt_elem_cola)); }*/ //////////////////////////////// return TRUE; } //************************************************************************************* /** * Rellena la matriz de distancias entre todas las conjunciones, es la parte de cálculos que * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué conjunciones le tocan. */ void Colv_limp_thr::calcula_cost_conj_sub(int ithr) { int nd,i,k,ics[2]; int n_ini, n_desp, n_fin, seg; float cost,cost2; BOOL mal=FALSE; Param_olv_limp_thr pp; int nent, refent; CartoBaseInfoEntity ient; //////////////// nent=olv_limp->carto.getNumberEntities(); mal=FALSE; pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso n_desp = (int)ceil(1.0*(nent)/n_subthr); n_ini= min(ithr*n_desp, nent); n_fin = min((ithr+1)*n_desp,nent); cost=cost2=0; nd=0; //////////////// olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Entidades %04d a %04d", ithr,n_ini, n_fin); seg = GetTickCount(); ///////////////////////////////////// //bucle por cada entidad de la carto for(i=n_ini; icarto.get(i); refent = ient.entity()->ref; for(k=0;k<2;k++) ics[k]=olv_limp->iaso[refent].inod[k]; if(ics[0]<0 || ics[1]<0) continue; /////////////////// //pone en el array de tipos qué es olv_limp->tip_conj.set(ics[0],ics[1],refent); olv_limp->tip_conj.set(ics[1],ics[0],refent); /////////////////////////////////// nd+=2; //ya tiene una línea y sus dos extremos localizados, calcula el coste calcula_cost(refent,&cost,&cost2); //añade los costes a la matriz if(cost>olv_limp->cost_conj[ics[0]][ics[1]]) cost=olv_limp->cost_conj[ics[0]][ics[1]]; olv_limp->cost_conj.set(ics[0],ics[1], min(cost,olv_limp->cost_conj[ics[0]][ics[1]])); if(cost2>olv_limp->cost_conj[ics[1]][ics[0]]) cost2=olv_limp->cost_conj[ics[1]][ics[0]]; olv_limp->cost_conj.set(ics[1],ics[0],min(cost2,olv_limp->cost_conj[ics[1]][ics[0]])); ///////////////////////////////////// //avisa de progreso if(((i-n_ini)%800==0) || ((i-n_ini)==(n_desp-1))) { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Rellenando matriz de dist entre conjs %ld de %ld", ithr, (i-n_ini+1),n_desp); //avisa de progreso prog_subthr=((1.0*(i-n_ini+1)/n_desp)+0)/3;///3 porque es la tercera parte del progreso los costes de conjunciones y la otra mitad los costes de ámbitos thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); } } olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin Matriz de dist entre conjs, %ld distancias, %.3f seg", ithr, nd,1.0*(GetTickCount()-seg)/1000); thr_padre->encola(OLV_LIMP_EV_COST_CONJ_FIN,NULL,FALSE); } //************************************************************************************* /** * Calcula el coste de la línea io, cost en sentido ida y cost2 en sentido vuelta */ void Colv_limp_thr::calcula_cost(int refent, float *cost, float *cost2) { double ltot; *cost=*cost2=0; //////////////////// ltot=0; if(olv_limp->carto.getRef(refent).entity()->type == CartoBaseTypes::Line) { ltot=olv_limp->carto.getRef(refent).getLong(); if(ltot==0) { //es un segmento de unión de peat con rep o de eje de calle con nw cost=cost2=0; return; } } /////////////////// olv_limp->dame_cost(ltot,refent,cost,cost2); } //************************************************************************************* /** * Rellena la matriz de ángulos entre las conjunciones adyacentes a una dada */ BOOL Colv_limp_thr::calcula_ang_conj() { //////////////// olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de ángulos entre conjunciones"); pon_mi_progre(OLV_TAREA_COST_AMB, (int) (OliviaDef::GeneralDef::ProgrMax*1/3)); pon_mi_msg("Rellenando matriz de ángulos entre nodos"); err_str[0]=0; //pide memoria para el array de distancias entre conjunciones olv_limp->ang_conj = new Djkt_ang_ady[olv_limp->conjs.n]; //lanza los threads lanza_subthrs(OLV_LIMP_EV_ANG_CONJ_SUB); return TRUE; } //************************************************************************************* /** * Rellena la matriz de ángulos entre todas las conjunciones. * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado */ BOOL Colv_limp_thr::calcula_ang_conj_fin() { //////////////// //para los threads para_subthrs(); revisa_calles_cortadas(); ////////////////////////////////// //calcula si va a ser multitask o no CoptiMemo oo; //se deja a false siempre de momento olv->modo_multitask=FALSE;//oo.is_multi(olv_limp->conjs.n,n_subthr,sizeof(Djkt_elem_cola)); ////////////////////////////////// olvlog(LOG_TODO,"olv_limp_t","FIN Matriz de ang entre conjs %ldx%ld", olv_limp->conjs.n,olv_limp->conjs.n); return TRUE; } //************************************************************************************* /** * Rellena la matriz de ángulos entre todas las conjunciones adyacentes a una dada, es la parte de cálculos que * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué conjunciones le tocan. */ void Colv_limp_thr::calcula_ang_conj_sub(int ithr) { Param_olv_limp_thr pp; int i,j,nconj,KK,na,ic,nady,nn; int n_ini, n_desp, n_fin, seg; BOOL mal=FALSE; BYTE aa; BYTE *conjs; double ang; //////////////// pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso KK=olv_limp->tipo_ambit; nconj=olv_limp->conjs.n; n_desp = (int)ceil(1.0*nconj/n_subthr); n_ini= min(ithr*n_desp, nconj); n_fin = min((ithr+1)*n_desp,nconj); na=nn=0; conjs=NULL; conjs=(BYTE*)malloc(olv_limp->conjs.n*sizeof(BYTE)); if(!conjs) mal=TRUE; else memset(conjs,0,olv_limp->conjs.n*sizeof(BYTE)); //////////////// olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Ángulos de conjunciones %04d a %04d", ithr,n_ini, n_fin); seg = GetTickCount(); ///////////////////////////////////// //bucle por cada conjunción de la carto for(ic=n_ini; icconjs.n*sizeof(BYTE)); //Busca conjunciones adyacentes for(i=0;icost_conj[i][ic]>=MAYUSCULO) && (olv_limp->cost_conj[ic][i]>=MAYUSCULO)) continue; //marca las conjunciones que son adyacentes conjs[i]=1; for(j=i+1;jcost_conj[ic][j]>=MAYUSCULO) { continue; } //marca las conjunciones que son adyacentes conjs[j]=1; } } for(i=0;i16) { nady=nady; } //ya tiene las adyacentes de la conjunción ic, inicializa array de angulos if(!olv_limp->ang_conj[ic].inicia(nady)) { mal=TRUE; break; } //Busca conjunciones adyacentes for(i=0;icost_conj[i][ic]>=MAYUSCULO) || (olv_limp->cost_conj[ic][j]>=MAYUSCULO)) { aa=0; } else { //si no hay restricciones de circulación, se pone que se el ángulo es ok siempre //si no, se calcula, y el ángulo es ok si es menor que el ángulo límite //if(olv_limp->res_circ!=OLV_RES_NO) { ang=dame_ang_conj(ic,i,j); aa=(ang<=olv_limp->ang_lim); nn++; } } olv_limp->ang_conj[ic].pon_ang_i_j(i,j,aa); na++; } } //avisa de progreso if(((ic-n_ini)%500==0) || ((ic-n_ini)==(n_desp-1))) { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Rellenando matriz de ang entre conjs %ld de %ld", ithr, (ic-n_ini+1),n_desp); //avisa de progreso prog_subthr=((1.0*(ic-n_ini+1)/n_desp)+1)/3;///3 porque es la tercera parte del progreso los costes de conjunciones thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); } } if(conjs) free(conjs); olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin Matriz de ang entre conjs, %ld ángulos, %ld dist 0, %.3f seg", ithr, na,nn,1.0*(GetTickCount()-seg)/1000); thr_padre->encola(OLV_LIMP_EV_ANG_CONJ_FIN,NULL,FALSE); } //************************************************************************************* /** * Devuelve el ángulo entre dos conjunciones */ double Colv_limp_thr::dame_ang_conj(int ic, int i, int j) { double ang, *p, v[2][2]; int npts,k,t; CartoBaseInfoEntity ient; int refconj_i = olv_limp->tip_conj[i][ic]; int refconj_j = olv_limp->tip_conj[j][ic]; ang=0; //cambio de sentido en carretera o ámbito if(i==j) { if((olv_limp->iaso[refconj_i].flgs & OLV_LIMP_FLG_NW) || (olv_limp->iaso[refconj_j].flgs & OLV_LIMP_FLG_NW)) { if(olv_limp->res_circ==OLV_RES_NO) return 0; else return OLV_PI;//ángulo de 180º en carretera y sigue sentidos, no se puede (excepto si es calle cortada, que se revisa luego) } else return 0; } if(!(olv_limp->iaso[refconj_i].flgs & OLV_LIMP_FLG_NW) || !(olv_limp->iaso[refconj_j].flgs & OLV_LIMP_FLG_NW)) { return 0;//uno de los dos no son carretera, se puede siempre } if(((olv_limp->iaso[refconj_i].flgs & OLV_LIMP_FLG_NW_REP) && (olv_limp->iaso[refconj_i].refe2 == refconj_j)) || ((olv_limp->iaso[refconj_j].flgs & OLV_LIMP_FLG_NW_REP) && (olv_limp->iaso[refconj_j].refe2 == refconj_i))) { //si intenta ir de nw a réplica, pero de la misma calle return OLV_PI; } //return 0; //las dos son carretera, mira si por coste no se puede ir //calcula los puntos próximos a la conjunción for(t=0;t<2;t++) { if(t==0) ient = olv_limp->carto.getRef(refconj_i); else ient = olv_limp->carto.getRef(refconj_j); p=ient.getPto(0); npts=ient.getNumberPtos(); if(Colv_geom::pto_equals(olv_limp->conjs.coor[ic], p)) { p=ient.getPto(1); //la conjunción es el primer punto for(k=0;k<2;k++) { v[t][k]=p[k]-olv_limp->conjs.coor[ic][k]; } } else { p=ient.getPto(npts-2); //la conjunción es el último punto for(k=0;k<2;k++) { v[t][k]=p[k]-olv_limp->conjs.coor[ic][k]; } } } ang=Colv_geom::ang_vect(v[0],v[1]); ang=OLV_PI-ang; return ang; } //************************************************************************************* /** * Resvisa los ángulos, de forma que si hay algún giro "prohibido" de 180º, en caso * de que sean calles cortadas o sin salida, los pone a ok */ void Colv_limp_thr::revisa_calles_cortadas() { int ic,i,j,k,nady; //if(olv_limp->res_circ==OLV_RES_NO) // return; for(ic=0;icconjs.n;ic++) { nady=olv_limp->ang_conj[ic].nady; for(i=0;iang_conj[ic].angs[i][j]) { //si el ángulo es prohibido, mira a ver si hay más conjunciones for(k=0;kang_conj[ic].i_conjs[k]<0 || olv_limp->ang_conj[ic].i_conjs[k]>=olv_limp->conjs.n) { olvlog(LOG_TODO,"olv_limp_t","Ojo ang_conj fuera de límites ic %ld, k %ld",ic,k); continue; } /*if(((k!=i) || (k!=j)) && (olv_limp->conjs.inc[olv_limp->ang_conj[ic].i_conjs[k]].n>1)) break;*/ if((olv_limp->ang_conj[ic].i_conjs[k]!=olv_limp->ang_conj[ic].i_conjs[i]) && (olv_limp->ang_conj[ic].i_conjs[k]!=olv_limp->ang_conj[ic].i_conjs[j]) && (olv_limp->cost_conj[ic][olv_limp->ang_conj[ic].i_conjs[k]]conjs.inc[olv_limp->ang_conj[ic].i_conjs[k]].n>1)) break; } if(k>=nady)//estos nodos son los únicos que tiene para entrar y salir { olv_limp->ang_conj[ic].angs[i][j]=1; } } } } } } //************************************************************************************* /** * Rellena la matriz de costes entre todos los ámbitos */ BOOL Colv_limp_thr::calcula_cost_amb() { //////////////// olvlog(LOG_TODO,"olv_limp_t","Rellenando matriz de costes entre ámbitos"); pon_mi_progre(OLV_TAREA_COST_AMB, (int) (OliviaDef::GeneralDef::ProgrMax*2/3)); pon_mi_msg("Rellenando matriz de costes entre ámbitos. %ld ámbitos por calcular",olv_limp->n_amb); err_str[0]=0; char st[MAX_PATH]; char st1[MAX_PATH]; strcpy_s(st1,MAX_PATH,olv_limp->olv->paths.path_temp); if(st1[strlen(st1)-1]=='\\') { st1[strlen(st1)-1]=0; } sprintf(st,"%s\\%s",st1,NOMB_ARCH_DIJ_DEF); //inicia archivo para los djistra-------------- if(!olv_limp->arch_dj.inicia(st,!olv->modo_multitask,olv_limp->conjs.n)) { olvlog(LOG_TODO,"olv_limp_t","Error al iniciar archivo dj en directorio %s",st); return FALSE; } if(!olv_limp->arch_dj.inicia_inf_amb(&olv_limp->iaso,olv_limp->n_amb,olv_limp->tipo_ambit,olv_limp->nod_instal, olv_limp->nod_plant)) { olvlog(LOG_TODO,"olv_limp_t","Error al iniciar info de ambitos en archivo de dj"); return FALSE; } //////////////////////////////////////////////// if(!inicia_cost_amb()) { return FALSE; } if(!olv_limp->olv->modo_multitask) { //lanza los threads, tiene memo suficiente para todos los threads lanza_subthrs(OLV_LIMP_EV_COST_AMB_SUB); } else { //en modo multitask entra aquí cuando ya han terminado las tasks //se lee la matriz de ámbitos que han guardado las tasks if(!olv_limp->arch_dj.lee_dis()) return FALSE; if(!olv_limp->olv_tasks->lee_cost_amb(olv_limp->cost_amb)) return FALSE; //borra los archivos temporales borra_temp_files(FALSE); //después de leerla, encola el cost_amb_fin for(int i=0;iprog_subthr=0;//para que no dé error encola(OLV_LIMP_EV_COST_AMB_FIN,NULL,FALSE); } } return TRUE; } //************************************************************************************* BOOL Colv_limp_thr::inicia_cost_amb() { int i,j; //pide memoria para el array de distancias entre ámbitos if(!olv_limp->cost_amb.inicia(olv_limp->n_amb,olv_limp->n_amb)) { pon_mi_msg("Error, sin memoria para matriz de dist entre ámbitos"); return FALSE; } //inicializa todo a 0 for(i=0;in_amb;i++) { for(j=0;jn_amb;j++) olv_limp->cost_amb[i][j]=(float)MAYUSCULO;//porque se va a almacenar la minima } //Inicia el array de orden /secuencia olv_limp->ord_sec=(Secu_amb*)malloc(sizeof(Secu_amb)*olv_limp->n_amb); if(!olv_limp->ord_sec) { pon_mi_msg("Error, sin memoria para matriz de orden y secuencia"); return FALSE; } memset(olv_limp->ord_sec,0,sizeof(Secu_amb)*olv_limp->n_amb); return TRUE; } //************************************************************************************* /** * Rellena la matriz de distancias entre todos los ámbitos. * El thread entra aquí cuando los subthreads que realizan la tarea realmente han finalizado */ BOOL Colv_limp_thr::calcula_cost_amb_fin() { //////////////// int ai=1; if(!olv_limp->olv->modo_multitask) { //para los threads para_subthrs(); } if(pirate) return FALSE; //////////////// //mira si hay aislados if(!avisa_aislados()) return FALSE; //avisa aislados ha ido bien, no hay aislados if(pirate) return FALSE; //calcula el coste a las plantas if(!calcula_cost_plant()) { pon_mi_msg("Error, planta o instalación aisladas"); return FALSE; } olv_limp->nsec_act=olv_limp->nsec; olvlog(LOG_TODO,"olv_limp_t","FIN Matriz de dist entre ámbitos %ldx%ld", olv_limp->n_amb,olv_limp->n_amb); return TRUE; } //************************************************************************************* /** * Dado el array relleno con los aislados, saca cartel avisando */ BOOL Colv_limp_thr::avisa_aislados() { int i,j,k,ii, ref_i, ref_j; BYTE *ambs_ais; char ais_msg[OLV_MAX_MSG_PROCE]; char nfile[MAX_PATH]; strcpy_s(nfile,MAX_PATH,olv->paths.path_data); //cambiaext(nfile,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); ambs_ais = (BYTE*)malloc(olv_limp->n_amb); if(!ambs_ais) { pon_mi_msg("Error, sin memoria en fin de calcula coste ámbitos"); return FALSE; } memset(ambs_ais,0,olv_limp->n_amb); //revisa costes de ámbitos int nais; for(i=0;in_amb; i++) { if(ambs_ais[i]) continue; ref_i=olv_limp->carto.get(i).entity()->ref; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; for(j=0;jn_amb; j++) { if(i==j) continue; ref_j=olv_limp->carto.get(j).entity()->ref; if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB_NO) continue; if(ambs_ais[j]) continue; if(olv_limp->cost_amb[i][j]>=MAYUSCULO) { //puede estar aislado i o j nais=0; for(k=0;kn_amb;k++) { if(k==i) continue; if(olv_limp->cost_amb[k][j]>=MAYUSCULO)//comprueba si j está aislado para los demás ámbitos también { nais=j; break; } if(k==j) continue; if(olv_limp->cost_amb[i][k]>=MAYUSCULO)//comprueba si i está aislado para los demás ámbitos también { nais=i; break; } } if(kn_amb) ambs_ais[nais]=1; } } } nais=0; int inw,inw2; INT64 flgs2; for(i=0;in_amb;i++) { if(ambs_ais[i]) { nais++; inw=olv_limp->inww_amb[i].refnw; if(olv_limp->tipo_ambit==OLV_AMB_LIN) { inw2=olv_limp->inww_amb[i+olv_limp->n_amb].refnw; flgs2=olv_limp->iaso[inw2].flgs; } else { inw2=0; flgs2=0; } olvlog(LOG_TODO,"olv_limp_t","Ámbito %05d aislado, inw1 %05d inw2 %05d, flags amb %02X inw1 %02X inw2 %02X ",i,inw,inw2, olv_limp->iaso[i].flgs,olv_limp->iaso[inw].flgs,flgs2); } } if(!nais) { free(ambs_ais); return TRUE; } if(nais==1) sprintf_s(ais_msg,"Encontrado %ld ámbito aislado %s: ", nais,olv_limp->igno_ais?"(Se ignora)":""); else sprintf_s(ais_msg,"Encontrados %ld ámbitos aislados %s: ",nais,olv_limp->igno_ais?"(Se ignoran)":""); int inais=0; for(i=0;in_amb;i++) { if(ambs_ais[i]) { ref_i=olv_limp->carto.get(i).entity()->ref; if(olv_limp->igno_ais)//si toca ignorar aislados, lo marca para ignorarlo en la sectorización { olv_limp->iaso[ref_i].flgs|=OLV_LIMP_FLG_AMB_NO; } ii=olv_limp->iaso[ref_i].oid; if(nais==1) { sprintf_s(ais_msg,"%s %ld",ais_msg,ii); break; } else if(inais==nais-1) sprintf_s(ais_msg,"%s y %ld",ais_msg,ii); else if(inais>0 && inais%4==0) sprintf_s(ais_msg,"%s %ld,\n",ais_msg,ii); else sprintf_s(ais_msg,"%s %ld,",ais_msg,ii); if(strlen(ais_msg)+10>=OLV_MAX_MSG_PROCE) break; inais++; } } if(in_amb && nais>1 && ((strlen(ais_msg)+5)igno_ais) Sleep (OLV_T_SLEEP_MSG); //////////////////////////// free(ambs_ais); if(olv_limp->igno_ais) return TRUE; else return FALSE; } //************************************************************************************* /** * Apunta en qué nodos está la planta y la instalación */ BOOL Colv_limp_thr::calcula_cost_plant() { int ic,ia,ka,nais,k, ref_ia; Djkt_nodo *costes_nodos; BOOL mal=FALSE; if(olv_limp->nod_instal<0) return TRUE; //Inicia el array de orden /secuencia olv_limp->ord_sec_plan=(Secu_amb*)malloc(sizeof(Secu_amb)); if(!olv_limp->ord_sec_plan) { pon_mi_msg("Error, sin memoria para matriz de orden y secuencia"); return FALSE; } memset(olv_limp->ord_sec_plan,0,sizeof(Secu_amb)); olvlog(LOG_TODO,"olv_limp_t","Calculando coste a planta e instalación"); costes_nodos=NULL; k=0; ic=olv_limp->nod_instal; if(!Colv_geom::dijkstra_ang_inv_ok(olv_limp->cost_conj, olv_limp->ang_conj, olv_limp->conjs.n, ic, &costes_nodos, &visto_ang)) { pon_mi_msg("Error al calcular costes de ámbitos a instalación"); return FALSE; } olv_limp->ord_sec_plan[k].ctnod[0]=costes_nodos; olv_limp->ord_sec_plan[k].ctnod[1]=NULL; costes_nodos=NULL; //revisa si está aislado de algún ámbito nais=0; for(ia=0;ian_amb;ia++) { ref_ia=olv_limp->carto.get(ia).entity()->ref; if(olv_limp->iaso[ref_ia].flgs & OLV_LIMP_FLG_AMB_NO) continue; for(ka=0;katipo_ambit;ka++) { if(olv_limp->ord_sec_plan[k].ctnod[0][olv_limp->iaso[ref_ia].inod[ka]].dis>=MAYUSCULO) { nais++; break; } } if(nais) break; } if(ian_amb) { pon_mi_msg("Error al calcular costes de ámbitos a instalación"); return FALSE; } return TRUE; } //************************************************************************************* /** * Rellena la matriz de distancias entre todos los ámbitos, es la parte de cálculos que * realizan los subthreads. 'ithr' indica qué thread es, para calcular qué ámbitos le tocan. */ void Colv_limp_thr::calcula_cost_amb_sub(int ithr) { int na_ini,na_fin,na_desp,na,i,k; int KK, seg; BOOL log_debug=FALSE; Djkt_nodo *costes_nodos; double caux; Param_olv_limp_thr pp; BOOL mal=FALSE; CartoBaseInfoEntity ient_na, ient_i; int ref_na, ref_i, amb_i, amb_na; //////////////// pp.id_e=OLV_TAREA_COST_AMB;//manda de parámetro la tarea de la que es el progreso KK=olv_limp->tipo_ambit; na_desp = (int)ceil(1.0*(olv_limp->n_amb)/n_subthr); na_ini= min(ithr*na_desp, olv_limp->n_amb); na_fin = min((ithr+1)*na_desp,olv_limp->n_amb); costes_nodos=NULL; //////////////// olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Ambs %04d a %04d", ithr,na_ini, na_fin); seg = GetTickCount(); ///////////////////////////////////// //Bucle por cada ámbito de los que le tocan a este thread ///////////////////////////////////// //el coste de un ámbito a sí mismo es el de trabajar ese ámbito, //que es el coste de ir de su conj inicial a la final na=na_ini; ///////////////////////////////////// for(na=na_ini;naias[i].ic_ini está almacenado el índice de la conjunción del nodo inicial del ámbito //y en olv_limp->ias[i].ic_fin el del final. ///////////////////////////////////////////// //calcula el coste máximo del ámbito na a todos los demás //los añade a la fila na de la matriz de costes //es coste máximo porque hace el máximo de: //inicio(na)->inicio(ni), inicio(na)->final(ni), final(na)->inicio(ni), final(na)->final(ni) ///////////////////////////////////////////// //k==0, calcula las distancias del nodo inicial de ese ámbito a todas las demás conjunciones //k==1, calucla las distancias del nodo final ient_na = olv_limp->carto.get(na); ref_na = ient_na.entity()->ref; amb_na=olv_limp->iaso[ref_na].iamb; for(k=0;kcost_conj, olv_limp->ang_conj, olv_limp->conjs.n, (1-k)*olv_limp->iaso[ref_na].inod[0]+k*olv_limp->iaso[ref_na].inod[1], &costes_nodos, &visto_ang)) { mal=TRUE; break; } //recorre todos los demás ámbitos buscando el coste a ellos en el array de costes devuelto, y los almacena //almacena el coste a su nodo inicial y a su nodo final if(olv_limp->iaso[ref_na].flgs & OLV_LIMP_FLG_AMB_NO) { for (i=0; iconjs.n; i++) { costes_nodos[i].dis=(float)MAYUSCULO; costes_nodos[i].id_padre=-1; costes_nodos[i].ids_ady.nady=0; } } else { for(i=0;in_amb;i++) { ient_i = olv_limp->carto.get(i); ref_i = ient_i.entity()->ref; amb_i=olv_limp->iaso[ref_i].iamb; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; if(na==i) { //el coste de un ámbito a sí mismo es el de trabajar ese ámbito olv_limp->cost_amb[amb_na][amb_na]=olv_limp->cost_conj[olv_limp->iaso[ref_na].inod[0]][olv_limp->iaso[ref_na].inod[1]]; continue; } if(olv_limp->cost_amb[amb_i][amb_na]>costes_nodos[olv_limp->iaso[ref_i].inod[0]].dis) olv_limp->cost_amb[amb_i][amb_na]=costes_nodos[olv_limp->iaso[ref_i].inod[1]].dis; if(KK==OLV_AMB_LIN) { if(olv_limp->cost_amb[amb_i][amb_na]>costes_nodos[olv_limp->iaso[ref_i].inod[0]].dis) olv_limp->cost_amb[amb_i][amb_na]=costes_nodos[olv_limp->iaso[ref_i].inod[1]].dis; } } } if(!olv_limp->arch_dj.add_b(costes_nodos, na, k, TRUE)) { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld,Error %ld no se ha podido guardar dj iref: %ld k: %ld", ithr, GetLastError(),na,k); } for(i=0;iconjs.n;i++) { costes_nodos[i].libera(); } free(costes_nodos); olv_limp->ord_sec[na].ctnod[k]=NULL; if(KK==1) olv_limp->ord_sec[na].ctnod[1]=NULL; } if(mal) break; //si es ámbito lineal calcula la distancia media de los cuatro nodos if(na==1) if(log_debug) { for(i=0;in_amb;i++) { if(olv_limp->cost_amb[amb_na][i]>=MAYUSCULO) caux=-1; else caux=olv_limp->cost_amb[amb_na][amb_i]; olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Coste ámb %ld a ámb %ld es %lf", ithr, na,i,caux); } } //avisa de progreso if(((na-na_ini)%100==0) || ((na-na_ini)==(na_desp-1))) { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Rellenando matriz de dist entre ambs %ld de %ld", ithr, (na-na_ini+1),na_desp); //avisa de progreso prog_subthr=((1.0*(na-na_ini+1)/na_desp)+2)/3;///3 porque es la tercera parte del progreso los costes de conjunciones thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); } } if(visto_ang) { free(visto_ang); visto_ang=NULL; } if(mal) { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en cálculo de matriz de distancias entre ámbitos", ithr); prog_subthr=-1;//para avisar al padre de que ha habido un error } else { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin Matriz de dist entre ambs, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); } thr_padre->encola(OLV_LIMP_EV_COST_AMB_FIN,NULL,FALSE); ///////////////////////////////////// } //************************************************************************************* /** * Genera los sectores */ BOOL Colv_limp_thr::sectoriza() { int i; BOOL res=TRUE; if(olv_limp->n_amb<2) { pon_mi_msg("Error, número de ámbitos es %ld",olv_limp->n_amb); return FALSE; } pon_mi_progre(OLV_TAREA_SECTORIZ, 0); pon_mi_msg(""); err_str[0]=0; if(!pide_memo_secto()) { pon_mi_msg("Error, Sin memoria para sectorización"); return FALSE; } ////////////////////////////////////////////////////////////// olvlog(LOG_TODO,"olv_limp_t","Comienza sectorización %ld ámbitos en %ld sectores", olv_limp->n_amb, olv_limp->nsec_act); /////////////////////////////////////// //Algoritmo 1 if(!sectoriza_1()) { pon_mi_msg("Errores producidos en sectorización: %s",err_str); res=FALSE; goto pinta; } /////////////////////////////////////// //Si es barrido mixto hay que copiar la info en las que no se ha sectorizado if(olv_limp->barr_mix) copia_info_barr_mix(); ////////////////////////////////////////////////////////////////////////////// //Guarda el shape añadiendo la columna de sector if(!guarda_dbf_sector(0)) { pon_mi_msg("Errores producidos en sectorización: %s",err_str); return FALSE; } //Guarda el shape añadiendo la columna de secuencia vacía if(!guarda_dbf_sector(1)) { pon_mi_msg("Errores producidos en sectorización: %s",err_str); return FALSE; } ////////////////////////////////////////////////////////////////////////////// for(i=0;insec;i++) { olvlog(LOG_TODO,"olv_limp_t","Sector %ld, %03d ámbitos, coste total %lf",i,olv_limp->sec[i].namb, olv_limp->sec[i].cost_ac); } olvlog(LOG_TODO,"olv_limp_t","Finalizada generacion de sectores--------------------------"); pinta: return res; } //************************************************************************************* /** * Pide memoria e inicializa los arrays para la sectorización */ BOOL Colv_limp_thr::pide_memo_secto() { int i,j; ////////////////////////////////////////////////////////////// //pide memoria para el array de distancias del sector olv_limp->sec = (Info_sec *)malloc(olv_limp->nsec*sizeof(Info_sec)); if(!olv_limp->sec) { pon_mi_msg("Error, sin memoria para matriz de sectores"); return FALSE; } memset(olv_limp->sec,0,olv_limp->nsec*sizeof(Info_sec)); for(i=0;insec;i++) { olv_limp->sec[i].iamb = (short *)malloc(olv_limp->n_amb*sizeof(short)); if(!olv_limp->sec[i].iamb) { pon_mi_msg("Error, sin memoria para matriz de sectores"); return FALSE; } } //inicializa todo a mayúsculo for(i=0;insec;i++) { olv_limp->sec[i].namb=0; olv_limp->sec[i].iamb_ini_def=-1; olv_limp->sec[i].sec_def = i+1; olv_limp->sec[i].t_despl[0]=olv_limp->sec[i].t_despl[1]=(float)olv_limp->t_despl; for(j=0;jn_amb;j++) { olv_limp->sec[i].iamb[j]=-1; } } ////////////////////////////////////////////////////////////// //pide memoria para el array de ámbitos asignados al sector olv_limp->amb_sec = (Info_amb_sec *)malloc(olv_limp->n_amb*sizeof(Info_amb_sec)); if(!olv_limp->amb_sec) { pon_mi_msg("Error, sin memoria para matriz de ámbitos en los sectores"); return FALSE; } memset(olv_limp->amb_sec,0,olv_limp->n_amb*sizeof(Info_amb_sec)); //inicializa todo for(j=0;jn_amb;j++) { olv_limp->amb_sec[j].sec=-1; olv_limp->amb_sec[j].iseq=-1; olv_limp->amb_sec[j].t=0; } olv_limp->nsec_orig=olv_limp->nsec; return TRUE; } //************************************************************************************* /** * Añade el ámbito 'i_amb' al sector 'i_sec', actualizando la info en todos los lugares necesarios */ BOOL Colv_limp_thr::add_amb_sec(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb, double cost_tot, int i_amb_p) { if(olv_limp->iaso[olv_limp->carto.get(i_amb).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) return FALSE; ss[i_sec].iamb[ss[i_sec].namb]=i_amb; ss[i_sec].namb++; //apunta el ámbito al sector aa[i_amb].sec=i_sec; return TRUE; } //************************************************************************************* /** * Le quita el ámbito 'i_amb' al sector 'i_sec', actualizando la info en todos los lugares necesarios * Actualiza el coste que es el que lleva, mas el desplazamiento del que ya tiene al nuevo, más el coste del nuevo * Al salir, hay que actualizar las distancias! */ void Colv_limp_thr::quita_amb_sec(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb, int i_amb_p) { int i,j; for(i=0;i=ss[i_sec].namb) return ; //no lo tenía este sector //le quita de su array de índices si tiene al menos uno posterior for(j=i;j &cost_amb, Info_sec *ss, Info_amb_sec *aa) { int s, i,ii, j, k; double d, dmax; BOOL sec_cerc; //busca elementos------------------------------- add_amb_sec(iamb_extr,n_amb,0,ss,aa,cost_amb,MAYUSCULO,-1); //busca ambitos extremos-------------------- for(s=1; s=0) continue; if(olv_limp->iaso[olv_limp->carto.get(j).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente { aa[j].sec=-1; continue; } for (ii=0; ii=0) break; } if(!sec_cerc && ii=0) continue; if(olv_limp->iaso[olv_limp->carto.get(j).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente continue; add_amb_sec(j,n_amb,n_sec-1,ss,aa,cost_amb,MAYUSCULO,-1); k=j; } return TRUE; } //************************************************************************************* /** * Añade el ámbito 'i_amb' al sector 'i_sec', actualizando la info en todos los lugares necesarios * Actualiza el coste que es el que lleva, mas el desplazamiento del que ya tiene al nuevo, más el coste del nuevo */ BOOL Colv_limp_thr::add_amb_sec_cost(int i_amb, int namb, int i_sec, Info_sec *ss, Info_amb_sec *aa, Matrix2d &cost_amb) { if(olv_limp->iaso[olv_limp->carto.get(i_amb).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) return FALSE; ss[i_sec].iamb[ss[i_sec].namb]=i_amb; ss[i_sec].namb++; //apunta el ámbito al sector aa[i_amb].sec=i_sec; //actualiza el coste del sector //si no es el primer ámbito, suma el coste de ir del anterior a este double dmed; int k; dmed=0; if(ss[i_sec].namb>1) { //calcula la distancia media entre los extremos for(k=0; k<3*olv_limp->tipo_ambit-2; k++) { dmed+=olv_limp->arch_dj.dame_dis(ss[i_sec].iamb[ss[i_sec].namb-1], k/2, i_amb,k%2); } dmed=dmed/(3*olv_limp->tipo_ambit-2); ss[i_sec].cost_ac+=(float)dmed; } //suma el coste de hacer el ámbito ss[i_sec].cost_ac+=cost_amb[i_amb][i_amb]; return TRUE; } //************************************************************************************* /** * Prueba sectorizacion algoritmo 1, expansion desde los mas dispares */ BOOL Colv_limp_thr::genera_sectores(int iamb_extr, int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) { int s, i,ii, j, jj, k, kk;//,jmin; double d, dmax,dmed; double cos_acum_sec; int *isec=NULL; int nord, isec_min; BOOL hay_cambio=TRUE; isec=(int*)malloc(n_sec*sizeof(int)); memset(isec,0,n_sec*sizeof(int)); if(!isec) return FALSE; //busca elementos------------------------------- add_amb_sec_cost(iamb_extr,n_amb,0,ss,aa,cost_amb); //busca ambitos extremos-------------------- for(s=1; s=0) continue; if(olv_limp->iaso[olv_limp->carto.get(j).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente { aa[j].sec=-1; continue; } d=DBL_MAX; for(i=0; i=i; k--) isec[k+1]=isec[k]; isec[i]=j; nord++; } isec_min=nord-1; hay_cambio=FALSE; } else { isec_min--; if(isec_min<0) { k=0; kk=0; for(j=0; j=0; ii--) { if(aa[aa[ss[j].iamb[i]].iamb_cerca[ii]].sec<0) kk++; } } } if(kk>0 || k!=n_amb) olvlog(LOG_TODO,"olv_limp_t","Error en la generacion de sectores, asignados %ld ambitos de %ld, existen %ld ambitos cercanos sin asignar",k, n_amb, kk); break;//todos asignados } } //intenta poner a sector de menor coste mas ambitos cos_acum_sec=-1; while(TRUE) { if(cos_acum_sec>=0) { if(cos_acum_sec==ss[isec[isec_min]].cost_ac) break; if(dmax=0; ii--) { j=aa[jj].iamb_cerca[ii]; if(aa[j].sec>=0) continue; //calcula la distancia media de ese ámbito cercano al sector al que lo intenta añadir dmed=dame_dmed_amb_sec(j,isec[isec_min]); if(dmed=d) break; if(aa[j].namb_cerca>2) { nord=0; //busca si resto de ramas estan pilladas l=-1; for (s=0; s1) break; if( l<0) l=aa[j].iamb_cerca[s]; } } if(nord>1 ||l<0) break; } else if(aa[j].namb_cerca>1) { if(aa[j].iamb_cerca[0]==jj) l=aa[j].iamb_cerca[1]; else l=aa[j].iamb_cerca[0]; } else break; jj=j; j=l; } if(dacum2) { nord=0; //busca si resto de ramas estan pilladas l=-1; for (s=0; s1) break; if(aa[j].iamb_cerca[s]!=jj && l<0) l=aa[j].iamb_cerca[s]; } } if(nord>1 || l<0) break; } else if(aa[j].namb_cerca>1) { if(aa[j].iamb_cerca[0]==jj) l=aa[j].iamb_cerca[1]; else l=aa[j].iamb_cerca[0]; } else break; jj=j; j=l; }*/ } } while (TRUE); free(isec); return TRUE; } //************************************************************************************* /** * Devuelve la distancia media del sector isec al ámbito iamb */ double Colv_limp_thr::dame_dmed_amb_sec(int iamb, int isec) { int i;//,j; double dmed, dmedtot; dmed=dmedtot=0; //se recorre todos los ámbitos del sector for (i=0; isec[isec].namb; i++) { dmed=dame_dmed_amb(i, iamb); dmedtot+=dmed/olv_limp->sec[isec].namb; } return dmedtot; } //************************************************************************************* /** * Devuelve la distancia media entre ámbitos (sobre todo para cuando son lineales) */ double Colv_limp_thr::dame_dmed_amb(int iamb1, int iamb2) { int k; double dmed; dmed=0; //calcula la distancia media entre los extremos de i e iamb for(k=0; k<3*olv_limp->tipo_ambit-2; k++) { dmed+=olv_limp->arch_dj.dame_dis(iamb1, k/2, iamb2,k%2); } dmed=dmed/(3*olv_limp->tipo_ambit-2); return dmed; } //************************************************************************************* /** * Prueba sectorizacion algoritmo pro, sectoriza basado en ámbitos, no en sectores */ BOOL Colv_limp_thr::genera_sectores_pro(int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) { std::map> sec; int i,j,jj,k,kk,s,s2,n,t; double dmin,d,d1; int nsec; int namb; BOOL mal=FALSE; int nmax, bloq; int oo[2]; //asigna cada ámbito a un sector namb=olv_limp->n_amb; bloq=1; n=0; for(i=0;iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente { aa[i].sec=-1; n++; continue; } aa[i].sec=i-n; sec[i-n].push_back(i); } nsec=namb-n; nmax=(int)(nsec/n_sec*1.3); //lo hace hasta que ya quedan solo el número de sectores que tienen que quedar while(nsec>n_sec) { dmin=DBL_MAX; k=kk=-1; //recorre los ámbitos, y coge el que tenga un ámbito que pertenezca a //otro sector que esté a la distancia mínima for(i=0;iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO)//se ha marcado para no usarse, por aislado o por carga insuficiente continue; //comprueba que el sector no esté creciendo demasiado if(sec[aa[i].sec].size()>nmax) continue; for(j=0;jnmax) continue; //////////////////////////////// //calcula la dist media entre el jj y todos los ámbitos del sector de i d=0; n=(int)sec[aa[i].sec].size(); for (t=0; tn_amb, olv_limp->amb_sec, olv_limp->ord_sec)) { sprintf_s(err_str,OLV_MAX_ERR,"Error al rellenar ambitos cercanos por carretera"); return FALSE; } //comprueba islas if(!quita_islas(olv_limp->n_amb, olv_limp->amb_sec, olv_limp->ord_sec)) { olvlog(LOG_TODO,"quita_islas","No consigue eliminar islas"); } ////////////////////// //Como primer ámbito coge el más extremo //el de menor 'y+x' maxx=MAYUSCULO; int ref_amb; for(i=0;in_amb;i++) { ref_amb = olv_limp->carto.get(i).entity()->ref; if(olv_limp->iaso[ref_amb].flgs & OLV_LIMP_FLG_AMB_NO) continue; if((olv_limp->conjs.coor[olv_limp->iaso[ref_amb].inod[0]][1]+olv_limp->conjs.coor[olv_limp->iaso[ref_amb].inod[0]][0])conjs.coor[olv_limp->iaso[ref_amb].inod[0]][1]+olv_limp->conjs.coor[olv_limp->iaso[ref_amb].inod[0]][0]; iamb=i; } } if((iamb<0) || (iamb>=olv_limp->n_amb)) { sprintf_s(err_str,OLV_MAX_ERR,"Error no se ha encontrado ambito extremo"); return FALSE; } if(pirate) { sprintf_s(err_str,OLV_MAX_ERR,"Sale por peticion de usuario"); return FALSE; } //si se ha calculado el número de sectores ya se ha sectorizado inicialmente, no hay que llamar a genera_sectores int nsec; if(olv_limp->calc_nsec==0) { nsec=olv_limp->nsec; } else { nsec=olv_limp->nsec_act; //entra aquí si ha calculado el número de sectores, y ya va a sectorizar //en este modo, primero usa solo los dos primeros sectores, al primero le da un ámbito y al segundo el resto de ámbitos } if(!genera_sectores_pro(nsec,olv_limp->cost_amb,olv_limp->sec, olv_limp->amb_sec)) { sprintf_s(err_str,OLV_MAX_ERR,"Error al generar sectores"); return FALSE; } guarda_dbf_sector(0); pon_mi_progre(OLV_TAREA_PERMU,0); if(olv_limp->nsec>1) { if(olv_limp->calc_nsec==0) { dd=iguala_sectores4(olv_limp->n_amb, olv_limp->nsec, olv_limp->cost_amb, olv_limp->sec, olv_limp->amb_sec); } else { //entra aquí si ha calculado el número de sectores, y ya va a sectorizar dd=iguala_sectores5(iamb,olv_limp->n_amb, olv_limp->nsec, olv_limp->cost_amb, olv_limp->sec, olv_limp->amb_sec); } olvlog(LOG_TODO,"olv_limp_t","Conseguida una desviación de: %lf",dd); } else { olv_limp->sec[0].cost_ac=(float)calcula_cost_1sec_total(olv_limp->n_amb,olv_limp->sec,olv_limp->ang_conj); if(olv_limp->sec[0].cost_ac>=MAYUSCULO) dd=-1; } if(dd<0)//si es -2, aislados, ya lo ha puesto el iguala_sectores4 { if(dd==-2) sprintf_s(err_str,OLV_MAX_ERR,"Existen ámbitos aislados que\nno ha sido posible unir a la red"); return FALSE; } return TRUE; } //************************************************************************************* /** * parte del ambito central del sector y crea el arbol de camino minimo de dicho sector marca en cada ambito quien es su padre y cuantos hijos tiene devuelve el numero de ambitos frontera **/ int Colv_limp_thr::asigna_padres(int amb_central, int namb, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa, int *buf, int nhijos_fron) { int i,j; int psel,sel; double d, dsel=MAYUSCULO; int nn=1; int oo[2]; for (i=0; inamb; i++) { if(aa[ss->iamb[i]].iseq!=-1) { olvlog(LOG_TODO,"olv_limp_t","Error en iasigna_padres, Ambito %d ya tiene padre asignados, sec %d",ss->iamb[i], aa[ss->iamb[i]].sec); } } buf[0]=amb_central; aa[amb_central].iseq=-2; aa[amb_central].t=0; while(nnnamb) { dsel=MAYUSCULO; sel=-1; for (i=0; inamb; j++)//recorre ambitos del sector { if(aa[ss->iamb[j]].iseq!=-1) continue; d=dis_min_amb(oo,buf[i],NULL, false,ss->iamb[j]);//cost_amb[buf[i]][ss->iamb[j]]; if(diamb[j]; psel=buf[i]; } } } if(sel<0) { olvlog(LOG_TODO,"olv_limp_t","Error en iasigna_padres, no encontrado ambitos libres sin padres"); break;//terminado (esto no deberia pasar) } if(aa[psel].iseq<0) aa[psel].iseq=sel; buf[nn]=sel; aa[sel].iseq=psel; aa[sel].t+=1; aa[psel].t+=1; nn++; } //recorre ambitos para pillar los ambitos frontera---------------- d=0; j=recorre_hijos(amb_central, namb, aa, NULL, 0, cost_amb, &d); if((j+1)!=nn) olvlog(LOG_TODO,"olv_limp_t","Error en iasigna_padres,Existen hijos aislados"); nn=0; for(j=0; jnamb; j++)//recorre ambitos del sector { if(aa[ss->iamb[j]].t<=nhijos_fron) buf[nn++]=ss->iamb[j]; } return nn; } //************************************************************************************* double Colv_limp_thr::dis_min_amb(int ids[2], int id_nod_ini, Secu_amb * ord_sec, BOOL res_nod, int iamb) { double dd=MAYUSCULO; double dis; double dd2=MAYUSCULO; ids[0]=ids[1]=0; CartoLine line1, line2; double p1[3], p2[3]; p1[2]=p2[2]=0; int i; //si puntuales, entra una vez, si lineales, entra cuatro for(int k=0; k<3*olv_limp->tipo_ambit-2; k++) { dis=olv_limp->arch_dj.dame_dis(id_nod_ini, k/2, iamb,k%2); if(disiaso[olv_limp->carto.get(id_nod_ini).entity()->ref].inod[ids[1]]; } //////////////////////////////////////////////////////////// if(OLV_PORC_LINRECT==0) dd2=0; else { if(olv_limp->tipo_ambit==OLV_AMB_LIN) { line1.pts.n=0; line2.pts.n=0; for(i=0;i<2;i++) { line1.addPto(olv_limp->conjs.coor[olv_limp->iaso[id_nod_ini].inod[i]]); line2.addPto(olv_limp->conjs.coor[olv_limp->iaso[iamb].inod[i]]); } dd2=line1.disMedLines(&line2); } else { dd2=GeometryFunction::Dist2d(olv_limp->conjs.coor[olv_limp->iaso[id_nod_ini].inod[0]],olv_limp->conjs.coor[olv_limp->iaso[iamb].inod[0]]); } //pasa de dist a segundos double velo; if(olv_limp->v_despl==0) velo=OLV_LIMP_VELO_CIRC_NW*OLV_KMH2MS; else velo=olv_limp->v_despl; dd2=dd2/velo; } //////////////////////////////////////////////////////////// //return dd; return dd*(1-OLV_PORC_LINRECT)+dd2*OLV_PORC_LINRECT; } //************************************************************************************* typedef struct Dists { double dist; int iamb; }Dists; //************************************************************************************* BOOL Colv_limp_thr::quita_islas(int namb, Info_amb_sec *aa, Secu_amb * ord_sec) { int nis =-1, i; if(namb<2) return true; short* islas = (short*) malloc(namb * sizeof(short)); if(!islas) return false; //marca todos los ambitos sin islas for (i=0;i amb_pend; for (i=0;iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) continue; if(islas[i]>-1) continue; nis++; amb_pend.push(i); while(!amb_pend.empty()) { int amb_act=amb_pend.top(); amb_pend.pop(); islas[amb_act]=nis; //añade cercanos a la pila for (int k =0 ; k-1) continue; amb_pend.push(aa[amb_act].iamb_cerca[k]); } } } olvlog(LOG_TODO,"quita_islas","Numero de islas %ld",nis); if(nis<1) goto va_bien; //quita islas int iamb=-1; int iamb_cerca=-1; int oo[2]; double dis, dd; for (int kis = nis; kis>0; kis--) { iamb=-1; iamb_cerca=-1; dis=MAYUSCULO; for (i=0; iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) continue; if(islas[i]!= kis) continue; for (int ii = 0; iiiaso[olv_limp->carto.get(ii).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) continue; if(islas[ii]== kis) continue; dd = dis_min_amb(oo,i,NULL, false,ii); if(ddconjs.n); if(!secu1) { olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","Sin memoria para ambitos"); return FALSE; } Dists dis_[MAX_LEN_BUF_CERCANAS]; rmax=RMAX_INI; //matriz de conexion con ambitos (te dice si una conjuncion esta conectada con un ambito y en ese caso con cual. -1 en caso contrario) conex = (int*) malloc(olv_limp->conjs.n * sizeof(int)); if (!conex) { olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","Sin memoria para conjunciones"); return FALSE; } for (n=0;nconjs.n;n++) conex[n]=-1; // matriz de distancias (olv_limp->cost_conj[][]) //olv_limp->tipo_ambit//indica que tipo de ambitos estamos tratando1 si es puntual 2 si es lineal //olv_limp->ias[0].ic[0]id de la conjunion 1 del ambito 0 //olv_limp->ias[0].ic[1]id de la conjunion 2 del ambito 0 //bucle por todos los ambitos //bucle por todos los nodos del ambito //bucle por todos los nodos //marcas en el array si el nodo es el del ambito o si tiene conexion directa con dicho ámbito for (n=0;nconjs.n;n++) { for (i=0;icarto.get(i).entity()->ref; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; for (j=0;jtipo_ambit;j++) { if (olv_limp->iaso[ref_i].inod[j]==n ) { //Ha encontrado que esta conjunción conecta con el ámbito iésimo conex[n]=i; //Sale de los dos bucles i=namb; break; } else if(olv_limp->cost_conj[n][olv_limp->iaso[ref_i].inod[j]]!=(float)MAYUSCULO && conex[n]==-1) { conex[n]=i; } } } } if(logdebug) { for(j=0;jconjs.n;j++) { olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","n %ld conex[n] %ld",j, conex[j]); } } secu2=&secu1[olv_limp->conjs.n]; for(j=0; jarch_dj.dame_buf_nodos(FALSE); buf_aux[1]=olv_limp->arch_dj.dame_buf_nodos(FALSE); if(!buf_aux[0] || !buf_aux[1]) { olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","Sin memoria para buffer de nodos"); goto va_mal; } for (j=0; jcarto.get(j).entity()->ref; if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB_NO) continue; cargado[0]=FALSE; cargado[1]=FALSE; for (i=0; icarto.get(i).entity()->ref; if(j==i) continue; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; //selecciona distancia minima de un ambito a otro dd=dis_min_amb(oo,i,&ord_sec[j], TRUE, j); if(dd>=MAYUSCULO)//sin conexion entre ambitos continue; //cargar ambito antes de archivo------------------- if(!cargado[oo[0]]) { olv_limp->arch_dj.get_b(j,oo[0],buf_aux[oo[0]]); cargado[oo[0]]=TRUE; } //se verifica que en los cercanos no se pase por los mismos nodos Colv_geom::ruta_dj_inv_ok(oo[1], secu1, buf_aux[oo[0]],olv_limp->conjs.n, &r1); //Recorre los nodos de la ruta entre esos ámbitos para ver si alguno de los nodos no conecta directamente //con algún ámbito, en cuyo caso lo descarta //o lo descarta también si lleva varios nodos de carretera seguidos rr=0; for (n=0;n0 && conex[secu1[n]]==-1 && conex[secu1[n-1]]==-1) rr++; else if( n<(r1-2)) rr=0; } if (n=MAX_LEN_BUF_CERCANAS) continue; aa[i].iamb_cerca[aa[i].namb_cerca]=j | (rr<<24); aa[i].namb_cerca++; } } //ordena------------- for (i=0;icarto.get(i).entity()->ref; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; memset(dis_,0,sizeof(Dists)*MAX_LEN_BUF_CERCANAS); if(aa[i].namb_cerca<=0) { aa[i].namb_cerca=aa[i].namb_cerca; olvlog(LOG_TODO,"rellena_amb_cercanos_por_carretera","iamb %ld 0 cercanos",i); continue; } for(j=0;j>24; dis_[j].dist=dis_min_amb(oo,i,&ord_sec[aa[i].iamb_cerca[j] & 0x00ffffff], TRUE, aa[i].iamb_cerca[j] & 0x00ffffff); dis_[j].iamb=aa[i].iamb_cerca[j]; } qsort(dis_,aa[i].namb_cerca,sizeof(Dists),Colv_limp_thr::compara_dist_cerc); if(logdebug) { for(j=0;j>24, dis_[j].dist); } } for(j=0;j0 ;j--) { r1=(aa[i].iamb_cerca[j-1] & 0xff000000)>>24; r2=(aa[i].iamb_cerca[j] & 0xff000000)>>24; if(r1>0 || r2>0) r1=r1; if((r2-r1)>RMAX_INI) aa[i].namb_cerca=j; } for(j=0;j>24); } aa[i].iamb_cerca[j]= aa[i].iamb_cerca[j] & 0x00ffffff; } } olv_limp->arch_dj.libera_buf(buf_aux[0]); olv_limp->arch_dj.libera_buf(buf_aux[1]); if(secu1) free(secu1); if(conex) free(conex); return TRUE; va_mal: olv_limp->arch_dj.libera_buf(buf_aux[0]); olv_limp->arch_dj.libera_buf(buf_aux[1]); if(conex) free(conex); if(secu1) free(secu1); return FALSE; } //************************************************************************************* /** * Compara las estructuras Dist. Las ordena por distancia */ int Colv_limp_thr::compara_dist_cerc (const void * a, const void * b) { //si adist - ((Dists*) b)->dist); } //************************************************************************************* /** * Busca el sector más cercano a un ámbito * busca el ambito frontera de iamb mas cercano al sector id_sec * si modo==1 busca se busca a cualquier sector menos id_sec */ int Colv_limp_thr::busca_sec_cerca_amb(Info_amb_sec *aa,int iamb, int id_sec, int modo) { int i,s,ia; if(id_sec<0) return -1; for(i=0; i=i; k--) isec[k+1]=isec[k]; isec[i]=j; nord++; } return isec; } //************************************************************************************* /** * Algoritmo 5 de igualación de sectores, pasando ámbitos de un sector a otro que tenga cerca */ double Colv_limp_thr::iguala_sectores5(int iamb, int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) { double desv; int res; enum Res{ RES_SALE_BIEN, RES_SALE_MAL, RES_NO_SALE, RES_GENERA, }; int i,j; desv=0; //llama al iguala_sect4 con, al principio sólo 2 sectores activos //luego comprueba si el último de los nsec su coste es mayor que la jornada //y si es así, nsec_act++, cuidando que no pase de nsec //se le añade un ámbito, el más lejano de nsec_act //si su coste es cero, nsec_act-- //si es el coste es >0 y <= que el coste jornada, todo ok do { olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 5 con %ld sectores", olv_limp->nsec_act); desv=iguala_sectores4( n_amb, olv_limp->nsec_act, cost_amb, ss, aa); if(desv<0) { //sale mal res=RES_SALE_MAL; continue; } if(ss[olv_limp->nsec_act-1].cost_ac==0) { if((olv_limp->nsec_act-1)<=0) { //sale bien, pero forzado, no debería salir por aquí.. res=RES_SALE_BIEN; continue; } olv_limp->nsec_act--; res=RES_GENERA; } else if(ss[olv_limp->nsec_act-1].cost_ac>olv_limp->calc_nsec) { //añade un sec activo, siempre que haya disponibles if((olv_limp->nsec_act+1)>olv_limp->nsec) { //sale bien, pero forzado, no debería salir por aquí.. res=RES_SALE_BIEN; continue; } olv_limp->nsec_act++; //llama de nuevo al genera_sectores res=RES_GENERA; } else { //sale bien res=RES_SALE_BIEN; } if(res==RES_GENERA) { ////////////////////////////////////////////////////////////// //reinicializa for(i=0;insec;i++) { olv_limp->sec[i].namb=0; olv_limp->sec[i].iamb_ini_def=-1; olv_limp->sec[i].t_despl[0]=olv_limp->sec[i].t_despl[1]=(float)olv_limp->t_despl; for(j=0;jn_amb;j++) { olv_limp->sec[i].iamb[j]=-1; } } //reinicializa for(j=0;jn_amb;j++) { olv_limp->amb_sec[j].sec=-1; olv_limp->amb_sec[j].iseq=-1; olv_limp->amb_sec[j].t=0; } ////////////////////////////////////////////////////////////// if(!genera_sectores3(iamb,olv_limp->n_amb,olv_limp->nsec_act,olv_limp->cost_amb,olv_limp->sec, olv_limp->amb_sec)) { //sale mal res=RES_SALE_MAL; } } } while (res>=RES_NO_SALE); if(res==RES_SALE_MAL) return -1; //si sale bien, libera el espacio libre if(olv_limp->nsec_actnsec) { for(int i=olv_limp->nsec_act;insec;i++) { if(olv_limp->sec[i].cost_amb_sec) { free(olv_limp->sec[i].cost_amb_sec); olv_limp->sec[i].cost_amb_sec = NULL; } if(olv_limp->sec[i].cost_amb_sec_aux) { free(olv_limp->sec[i].cost_amb_sec_aux); olv_limp->sec[i].cost_amb_sec_aux = NULL; } if(olv_limp->sec[i].iamb) { free(olv_limp->sec[i].iamb); olv_limp->sec[i].iamb = NULL; } } Info_sec* sec_aux; sec_aux=(Info_sec*)realloc(olv_limp->sec,olv_limp->nsec_act*sizeof(Info_sec)); if(!sec_aux) return -1; olv_limp->sec=sec_aux; olv_limp->nsec=olv_limp->nsec_act; } return desv; } //************************************************************************************* /** * Algoritmo 4 de igualación de sectores, pasando ámbitos de un sector a otro que tenga cerca */ double Colv_limp_thr::iguala_sectores4(int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa) { double desv; double desv_last,cos_min, cos_min_last, cos_max, cos_max_last; double desv_abs_old, desv_abs; double d, d1; BYTE* st=NULL; int *isec=NULL, *iamb_r=NULL, j, i, ii, jj,k; int sec_m=0; int sselc=-1; int iamb,ip, sec; int nth=Colv_geom::dame_n_nucleos(); Secu_amb * ord_sec=olv_limp->ord_sec; th_param_planif thp; memset(&thp, 0, sizeof(thp)); thp.milis_sleep=1; thp.namb_t=n_amb; thp.abs=TRUE; desv_last=dame_desv_sec(n_sec,ss, TRUE,&desv_abs_old); BOOL log_debug=FALSE; BOOL todo_ok=FALSE; BOOL aisladas=FALSE; char nfile[MAX_PATH]; BOOL nocalc=FALSE; ii=jj=0; iamb=-1; strcpy_s(nfile,MAX_PATH,olv->paths.path_data); //cambiaext(nfile,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); //////////////////////////////////////////// //avisa de progreso olvlog(LOG_TODO,"olv_limp_t","Calculando permutaciones para mejorar al igualar sectores"); pon_mi_progre(OLV_TAREA_PERMU,0); //////// thp.dth=(th_data_planif*)malloc(sizeof(th_data_planif)*nth); memset(thp.dth, 0, sizeof(th_data_planif)*nth); for (i=0; i=0) Sleep(1); } ///////////////////////////////////// sec=-1; desv=iguala_sectores3(n_amb, n_sec, cost_amb, ss, aa, ord_sec, &thp); if(desv>=MAYUSCULO) { sprintf_s(err_str,OLV_MAX_ERR,"Error en iguala_sect3"); goto salir; } desv_last=dame_desv_sec(n_sec,ss, TRUE, &desv_abs_old); olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 4. Desv: %lf",desv_last); if(olv_limp->calc_nsec<=0) cos_max_last=dame_mima(n_sec, ss,&cos_min_last); else cos_max_last=cos_min_last=0; iamb_r=(int*)malloc(sizeof(int)*n_amb*2); if(!iamb_r) { sprintf_s(err_str,OLV_MAX_ERR,"Error al pedir memoria"); goto salir; } st=guarda_estado(n_amb,n_sec,aa,ss,st); if(!st) { sprintf_s(err_str,OLV_MAX_ERR,"Error al guardar estado"); goto salir; } do { if(((desv_lastDESV_MAX) && (desv_abs_old<=olv_limp->DESV_MAX_ABS)) || (desv_abs_old<=olv_limp->DESV_MAX_ABS) || fin_permu) { todo_ok=TRUE; break; } //ordena sectores por coste-------------------------- isec=ordena_sec(n_sec,ss,isec); //selecciona sector a bloquear do { //elije un sector con mas de un ambito (para poder quitarle uno) sselc=isec[sec_m]; if(ss[sselc].namb>1) break; sec_m++; } while(sec_m>=n_sec-1); if(sec_m>=n_sec-1) { todo_ok=TRUE; break; } //busca ambito mas pequeño posible que tenga otro de otro sector más cerca d=MAYUSCULO; iamb=-1; for (i=0; iiaso[olv_limp->carto.get(ss[sselc].iamb[i]).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) continue; for (j=0; j=0) { d=d1; iamb=ss[sselc].iamb[i]; ip=k; sec=aa[k].sec; } } } if(d>=MAYUSCULO || sec<0) { sprintf_s(err_str,OLV_MAX_ERR,"Error, no encuentra más ámbitos cercanos"); if(desv=desv_last) { if(olv_limp->calc_nsec<=0 && desv==desv_last) cos_max=dame_mima(n_sec, ss, &cos_min); else cos_max=cos_min=0; if( desv>desv_last || (((cos_max-cos_min)>= (cos_max_last-cos_min_last)))) { //se vuelve a estado anterior pon_estado(n_amb,n_sec,aa,ss,cost_amb,st); desv=dame_desv_sec(n_sec,ss, TRUE); if(desv!=desv_last) olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 4. Error no coincide desv anterior Desv: %lf Desv_old",desv, desv_last); sec_m++; if(sec_m>=n_sec-1) { todo_ok=TRUE; break; } continue; } sec_m=0; } sec_m=0; olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 4. Cambio mejora desv old: %lf, new %lf",desv_last, desv); desv_last=desv; desv_abs_old=desv_abs; cos_max_last=cos_max; cos_min_last=cos_min; st=guarda_estado(n_amb,n_sec,aa,ss,st); if(!st) { sprintf_s(err_str,OLV_MAX_ERR,"Error al guardar estado anterior"); goto salir; } } while (!pirate); if(!todo_ok) goto salir; st=guarda_estado(n_amb,n_sec,aa,ss,st); if(!st) goto salir; /* if(olv_limp->calc_nsec>0) todo_ok=FALSE;//se reinicia para ver si la siguiente parte todo_ok while(olv_limp->calc_nsec>0 && !pirate) { if((desv_lastMAYUSCULO) continue; quita_amb_sec(iamb,n_amb,sselc,ss,aa,cost_amb,aa[iamb].iseq); add_amb_sec(iamb,n_amb,sec,ss,aa,cost_amb,MAYUSCULO,ip); for (ii=0; ii=desv_last) { //se vuelve a estado anterior pon_estado(n_amb,n_sec,aa,ss,cost_amb,st); desv=dame_desv_sec(n_sec,ss, TRUE); if(desv!=desv_last) desv_last=desv; continue; } olvlog(LOG_TODO,"olv_limp_t","Iguala sectores4. Cambio mejora desv old: %lf, new %lf",desv_last, desv); desv_last=desv; st=guarda_estado(n_amb,n_sec,aa,ss,st); if(!st) { sprintf_s(err_str,OLV_MAX_ERR,"Error al guardar estado"); goto salir; } break; } } if(i>=ss[sselc].namb) { todo_ok=TRUE; break; } } */ salir: if(log_debug) { olvlog(LOG_TODO,"olv_limp_t","------------------------------------------------"); for(i=0;i0) Sleep(1); if(iamb_r) free(iamb_r); if(st) free(st); free(isec); if(thp.dth) { if(thp.dth[0].sec) free(thp.dth[0].sec); free(thp.dth); } if(!todo_ok) { olvlog(LOG_TODO,"olv_limp_t","Errores varios en iguala_sectores4"); if(aisladas) return -2; return -1; } return desv_last; } //************************************************************************************* /** * Recorre los 'nesc' sectores igualando su coste * La idea es poner ambitos a los sectores de menor coste manteniendo la condicion de no aisladas */ #define MAX_AMBI_IGUALA_SEC 500 double Colv_limp_thr::iguala_sectores3(int n_amb, int n_sec, Matrix2d &cost_amb, Info_sec *ss, Info_amb_sec *aa, Secu_amb * ord_sec, th_param_planif *thp) { double desv,desv_last, desv_fut,desv_abs;//máxima desviación permitida respecto a la media BOOL hay_cambio,log_debug, prime; int *amb_fron;//indice a ambitos frontera de sectores int *isec=NULL;//indice a sectores (ordenados de mayor a menor) int *icerca;//indice a ambitos cercanos a los frontera de un sector int *icamb;//indices a ambitos cambiados de sector en un pasp int cambio[2][2];//[0]ambito y sector que se pasa al[1] ambito (padre) y sector int siz_sec=(n_amb+1); int j, i, k,kk, kkk; int isec_min; int ncerca; int nhijos_frontera=10; int namb_camb; int ind_camb; int nais=0; //------------------------------- log_debug=TRUE; if(log_debug) olvlog(LOG_TODO,"olv_limp_t","Empieza igualacion de sectores 3"); isec=(int*)malloc(sizeof(int)*(1+n_sec*(n_amb+1)+n_sec+n_amb*5)); memset(isec,0,sizeof(int)*(1+n_sec*(n_amb+1)+n_sec+n_amb*5)); desv_last=desv_abs=MAYUSCULO; prime=TRUE; if(!isec) { olvlog(LOG_TODO,"olv_limp_t","Error en igualacion de sectores 3, sin memoria para bufferes"); return desv_last;//no debería pasar } icerca=&isec[n_sec+1]; icamb=&icerca[n_amb*2]; amb_fron=&icamb[n_amb*3]; //calcula media y desviacion de costes en sectores //bucle hay_cambio=TRUE; ind_camb=-1; for(j=0; jDESV_MAX) && (desv_abs<=olv_limp->DESV_MAX_ABS)) || (desv_abs<=olv_limp->DESV_MAX_ABS) || fin_permu)//if(desv_lastcalc_nsec) { isec[0]=n_sec-1; ordena_sec(n_sec-1, ss, &isec[1]); isec_min=n_sec-1; } else { ordena_sec(n_sec, ss, isec); isec_min=n_sec-1; } hay_cambio=FALSE; if(log_debug && ind_camb>=0) olvlog(LOG_TODO,"olv_limp_t","Iguala sectores 3, mejorada desviacion tipica a %lf", desv_last); } else { isec_min--; if(isec_min<=0) break;//no se puede mejorar mas } //busca fronteras de otros sectores cercanas al sector isec_min if(ss[isec[isec_min]].flags_tem& OLV_LIMP_FLG_SEC_INFO_BLOCK) continue; ncerca=0; for(j=0; j=0; i--) { //verifica que tenga ambitos cercanos de otros sectores //si es asi añade al array k=busca_sec_cerca_amb(aa,amb_fron[kk+i], isec[isec_min],1); if(k>=0) { icerca[ncerca*2]=k; icerca[ncerca*2+1]=amb_fron[kk+i]; ncerca++; } } continue; } //recore ambitos frontera de sector j kk=isec[j]*siz_sec+1; for(i=amb_fron[isec[j]*siz_sec]-1; i>=0; i--) { k=busca_sec_cerca_amb(aa,amb_fron[kk+i], isec[isec_min]); if(k>=0) { icerca[ncerca*2]=amb_fron[kk+i]; icerca[ncerca*2+1]=k; ncerca++; } } } if(ncerca<=0) continue;//no se puede mejorar if(ncerca>n_amb) ncerca=ncerca; desv_fut=MAYUSCULO; ind_camb=-1; for(i=0; imilis_sleep=0; calcula_coste_1sec(ord_sec, &ss[cambio[0][1]], thp,FALSE); calcula_coste_1sec(ord_sec, &ss[cambio[1][1]], thp,FALSE); thp->milis_sleep=1; } //comprueba mejora o no----------------------- desv=dame_desv_sec(n_sec,ss,TRUE,&desv_abs); if(desvdesv) { desv_fut=desv; ind_camb=i; } } //se deshace el cambio-------------------------- for (j=0; jn_amb>=MAX_AMBI_IGUALA_SEC && ind_camb>=0) break; } if(ind_camb>=0) { cambio[0][0]=icerca[ind_camb*2];//se pone este cambio[0][1]=aa[cambio[0][0]].sec; cambio[1][0]=icerca[ind_camb*2+1];//con padre este cambio[1][1]=aa[cambio[1][0]].sec; namb_camb=1; icamb[0]=cambio[0][0]; icamb[1]=cambio[1][0]; icamb[2]=cambio[0][0]; for (j=0; jmilis_sleep=0; calcula_coste_1sec(ord_sec, &ss[cambio[0][1]], thp,FALSE); calcula_coste_1sec(ord_sec, &ss[cambio[1][1]], thp,FALSE); thp->milis_sleep=1; } //comprueba mejora o no----------------------- double desv_lastold=desv_last; desv_last=dame_desv_sec(n_sec,ss,TRUE,&desv_abs); if(desv_lastoldOJO -->El cambio selec empeora des_act:%lf desv_obt: %lf",desv_lastold, desv_last); //se deshace el cambio-------------------------- for (j=0; jOJO -->Se quita cambio y queda desv: %lf",desv_last); hay_cambio=FALSE; } else hay_cambio=TRUE; } else { hay_cambio=FALSE; } } while (TRUE); //fin ---------------------------------------------------------- if(isec) free(isec); if(FALSE) { olvlog(LOG_TODO,"olv_limp_t","------------------------------------------------"); for(i=0;icalc_nsec>0) { cost_med=olv_limp->calc_nsec; //impone el coste medio de los sectores, que es justo la jornada laboral nsec--; //se quita un sector, el último, para el cálculo de la media } else { for(j=0;jcalc_nsec>0) && (dd>0)) { dd+=cost_med*nsec*2; } aux=abs(dd); if(aux>cost_max) cost_max=aux; cost_med2+=dd*dd/nsec; } if(olv_limp->calc_nsec>0) { if(((ss[nsec].cost_ac-cost_med)>0))//si está en modo fijar jornada, tampoco queremos que se desmadre el último { aux=cost_med; if(aux>cost_max) cost_max=aux; cost_med2+=cost_med*cost_med/nsec; } } if(cost_med2>MINUSCULO) cost_med2=sqrt(cost_med2); else cost_med2=0; if(absol) *absol=cost_max; if(porc) return cost_med2/cost_med; else return cost_med2; } //************************************************************************************* /** * Calcula diferencia minima y maxima de costes entre sectores */ double Colv_limp_thr::dame_mima(int nsec, Info_sec *ss, double *mini) { int i; int j; double costmax=-MAYUSCULO; double costmin=MAYUSCULO; double dd; //calcula la desviación típica for(j=0;jcostmax) costmax=dd; if (ddiseq=aa[a].iseq; inf->sec=aa[a].sec; inf->t=aa[a].t; } for (a=0; a &cost_amb, BYTE* st ) { int i, k=0, s; Info_est_amb *inf; //prepara todo a 0--------------------- for (i=0; iiseq; aa[i].t=inf->t; aa[i].sec=inf->sec; s=inf->sec; if(s>=0) ss[s].iamb[ss[s].namb++]=i; } for (i=0; i &cost_amb, double *cost, BOOL inicia) { int i, h; int oo[2]; if(inicia) { for (i=0; iiaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) continue; if(aa[i].iseq!=iamb) continue; if(aa[i].res) continue; if(i==iamb) continue; aa[i].res=1; *cost+=dis_min_amb(oo,iamb,NULL, false,i)+cost_amb[i][i];//cost_amb[iamb][i]+cost_amb[i][i]; if(iamb_r) { iamb_r[namb_r*2]=i; iamb_r[namb_r*2+1]=iamb; } namb_r++; if(namb_r>namb) namb_r=namb_r; if(aa[i].t>1) namb_r=recorre_hijos(i,namb, aa, iamb_r, namb_r, cost_amb, cost, FALSE); h--; if(h<=-2) break; } return namb_r; } //************************************************************************************* /** * Actualiza la matriz de costes de los ámbitos a otros ámbitos */ BOOL Colv_limp_thr::actualiza_costes( int namb,int n_sec, Info_amb_sec *aa, Info_sec *ss, Matrix2d &cost_amb ) { int s, a, i, na, k, kk, p; double d; BOOL res=TRUE; for (a=0; a=namb) continue; na=ss[s].namb; ss[s].namb=1; ss[s].iamb[0]=a; ss[s].cost_ac=cost_amb[a][a]; aa[a].res=1; while(TRUE) { k=-1; d=MAYUSCULO; for(i=0; icost_amb[kk][a]) { d=cost_amb[kk][a]; p=kk; k=a; } } } if (k<0) { break; } ss[s].cost_ac+=cost_amb[p][k]+cost_amb[k][k]; aa[k].res=1; ss[s].iamb[ss[s].namb++]=k; } if(na!=ss[s].namb) res=FALSE; } return res; } //************************************************************************************* /** * Calcula el coste de desplazamiento de ir de ir por todos los ambitos sec desde ini hasta fin */ double Colv_limp_thr::dame_coste( Secu_amb * sec, int ini, int fin, Info_sec *s, BOOL ind_abs) { double d=0; int ind_cost,fin_old; fin_old=fin; while(iniiamb[sec[fin].iamb]; else ind_cost=sec[fin].iamb; d+=olv_limp->cost_amb[s->iamb[sec[fin].iamb]][s->iamb[sec[fin].iamb]]; d+=olv_limp->arch_dj.dame_dis(s->iamb[sec[fin-1].iamb],(sec[fin-1].entrada+1)%2,s->iamb[sec[fin].iamb],sec[fin].entrada); fin--; } d+=olv_limp->cost_amb[s->iamb[sec[ini].iamb]][s->iamb[sec[ini].iamb]]; if(ini==0)//si ini es 0 falta sumar el coste de la planta al primer ambito { if (ind_abs) ind_cost=s->iamb[sec[ini].iamb]; else ind_cost=sec[ini].iamb; if(olv_limp->nod_instal>=0) { int ee=0; if(sec[ini].entrada>=0) ee=sec[ini].entrada; d+=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[sec[ini].iamb],ee); //d+=sec[ind_cost].ctnod[ee][olv_limp->nod_instal].dis; } else d+=olv_limp->t_despl; } //suma el coste de ir del ultimo ambito a la instalación if(olv_limp->nod_instal>=0) d+=olv_limp->ord_sec_plan[0].ctnod[0][olv_limp->iaso[olv_limp->carto.get(s->iamb[sec[fin_old].iamb]).entity()->ref].inod[(sec[fin_old].entrada+1)%2]].dis; else d+=olv_limp->t_despl; return d; } //************************************************************************************* /** * Calcula el coste de desplazamiento de ir por todos los ambitos sec desde ini hasta fin * cambiando el ámbito de pos_old como si estuviera en pos_new */ double Colv_limp_thr::dame_coste_ex( Secu_amb * sec, int ini, int fin, Info_sec *s, int pos_old, int pos_new, int entrada ) { double d=0; int sig, act; int a_ent, s_ent; while(iniarch_dj.dame_dis(sec[act].iamb,a_ent,s->iamb[sec[sig].iamb],(s_ent+1)%2); d+=olv_limp->cost_amb[s->iamb[sec[act].iamb]][s->iamb[sec[act].iamb]]; ini++; } act=Colv_geom::dame_ind_per(ini,pos_old,pos_new); d+=olv_limp->cost_amb[s->iamb[sec[ini].iamb]][s->iamb[sec[ini].iamb]]; return d; } //************************************************************************************* /** * Lee la sectorización que viene como info asociada en el shp de entrada */ BOOL Colv_limp_thr::lee_secto() { BOOL ret; int i, s, idd, ics, icsq; char nfile[MAX_PATH]; int* info; Cb_file f; Fdbf dbf; int sector, secuen; ret = TRUE; std::map> l_sec; std::map> l_secuen; olvlog(LOG_TODO, "olv_limp_t", "Comienza lectura de sectorización"); pon_mi_progre(OLV_TAREA_LEE_SECTO, 0); pon_mi_msg(""); err_str[0] = 0; ///////////////////////////////////// info = (int*)malloc(olv_limp->n_amb * sizeof(int)); if (!info) { sprintf_s(err_str, OLV_MAX_ERR, "Error, sin memoria para info asociada"); return FALSE; } memset(info, 0, olv_limp->n_amb * sizeof(int)); //lee dbf del shp la columna SECTOR strcpy_s(nfile, MAX_PATH, olv->paths.path_data); //cambiaext(nfile,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(nfile)), "dbf"); if (!f.abre(nfile, 1) || !dbf.lee(&f)) { ret = FALSE; goto fin; } ics = dbf.findCol(olv_limp->camps.campo_secto); icsq = dbf.findCol(olv_limp->camps.campo_secuen); if (ics < 0 || icsq < 0) { ret = FALSE; goto fin; } idd = dbf.leeNexRow(); //rellena para cada sector info[i] qué ámbitos tiene for (i = 0; i < olv_limp->n_amb && idd == 1; i++) { if (olv_limp->iaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) { idd = dbf.leeNexRow(); continue; } sector = dbf.getI(ics); l_sec[sector].push_back(i);//va añadiendo al sector los elementos secuen = dbf.getI(icsq); if (secuen > 0)//se indica en qué secuencia va ese elemento { l_secuen[sector][secuen] = i; } idd = dbf.leeNexRow(); } if (i < olv_limp->n_amb) { ret = FALSE; goto fin; } olv_limp->nsec = (int)l_sec.size(); //////////////////////////////////////// //revisa si todos los ámbitos de todos los sectores tienen secuencia bool secuen_incompleta = false; bool secuen_vacia = true; for (std::map>::iterator it = l_secuen.begin(); it != l_secuen.end(); ++it) { if (secuen_vacia && (it->second.size() > 0)) secuen_vacia = false;//alguno de los sectores trae info de secuencia if (it->second.size()>0 && (l_sec[it->first].size() != it->second.size()))//no ha almacenado el mismo número de ámbitos en los dos arrays { secuen_incompleta = true; break; } for (i = 1; i < it->second.size()+1; i++) { if (it->second.find(i)==it->second.end()) //si alguna secuencia no existe { secuen_incompleta = true; break; } } } if (!secuen_vacia && secuen_incompleta) { //loguea error pon_mi_msg("Se descarta información de secuencia por encontrarse elementos incompletos o repetidos"); } //////////////////////////////////////// //inicia los arrays para la sectorización if (!pide_memo_secto()) { sprintf_s(err_str, OLV_MAX_ERR, "Error, Sin memoria para lectura de sectorización"); ret = FALSE; goto fin; } //////////////////////////////////////// //recoge los datos, revisando que estén las secuencias completas i = -1;//sector int ia = 0; for (std::map>::iterator it = l_sec.begin(); it != l_sec.end(); ++it) { i++; olv_limp->sec[i].sec_def = it->first; olv_limp->sec[i].namb = (int)it->second.size(); if(!secuen_vacia && ! secuen_incompleta)//se ha indicado toda la secuencia en l_secuen { olv_limp->sec[i].iamb_ini_def = -1;// l_secuen[it->first][1]; for (ia = 1; ia < olv_limp->sec[i].namb + 1; ia++) { olv_limp->sec[i].iamb[ia - 1] = l_secuen[it->first][ia]; olv_limp->amb_sec[l_secuen[it->first][ia]].sec = i; olv_limp->amb_sec[l_secuen[it->first][ia]].iseq = ia-1; } } else //añade los elementos según los ha leído { olv_limp->sec[i].iamb_ini_def = -1; for (ia = 0; ia < olv_limp->sec[i].namb; ia++) { olv_limp->sec[i].iamb[ia] = it->second[ia]; olv_limp->amb_sec[it->second[ia]].sec = i; } } } if (!secuen_vacia && !secuen_incompleta)//se ha indicado toda la secuencia en l_secuen { olv_limp->usa_secuen = TRUE; //loguea pon_mi_msg("Usa información de secuencia de la capa de entrada"); } fin: free(info); if (!ret) { pon_mi_msg("Error en lectura de info de sectorización: %s", err_str); } return ret; } //************************************************************************************* /** * Lee la sectorización que viene como info asociada en el shp de entrada */ BOOL Colv_limp_thr::lee_secto_old() { BOOL ret; int i,s,idd, ics, icsq; char nfile[MAX_PATH]; int *info; Cb_file f; Fdbf dbf; int sector, secuen; ret = TRUE; std::map> l_sec; std::map> l_sec_; olvlog(LOG_TODO,"olv_limp_t","Comienza lectura de sectorización"); pon_mi_progre(OLV_TAREA_LEE_SECTO, 0); pon_mi_msg(""); err_str[0]=0; ///////////////////////////////////// info = (int *)malloc(olv_limp->n_amb*sizeof(int)); if(!info) { sprintf_s(err_str,OLV_MAX_ERR,"Error, sin memoria para info asociada"); return FALSE; } memset(info,0,olv_limp->n_amb*sizeof(int)); //lee dbf del shp la columna SECTOR strcpy_s(nfile,MAX_PATH,olv->paths.path_data); //cambiaext(nfile,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(nfile)),"dbf"); if(!f.abre(nfile,1) || !dbf.lee(&f)) { ret=FALSE; goto fin; } ics=dbf.findCol(olv_limp->camps.campo_secto); icsq=dbf.findCol(olv_limp->camps.campo_secuen); if(ics<0 || icsq<0) { ret=FALSE; goto fin; } int j; bool indica_secuen = true; idd =dbf.leeNexRow(); //rellena para cada sector info[i] qué ámbitos tiene for(i=0;in_amb && idd==1; i++) { if(olv_limp->iaso[olv_limp->carto.get(i).entity()->ref].flgs & OLV_LIMP_FLG_AMB_NO) { idd=dbf.leeNexRow(); continue; } sector=dbf.getI(ics); if (l_sec[sector].size() == 0) { //inicializa el array con -1 //lo inicializa al número de ámbitos, no sabe a priori cuántos tendrá este sector for (j = 0; j < olv_limp->n_amb; j++) l_sec[sector].push_back(-1); } secuen = dbf.getI(icsq); if (secuen > 0)//se indica en qué secuencia va ese elemento l_sec[sector][secuen] = i; else { //no se indica secuencia, busca el primer elemento no inicializado for (j = 1; j < l_sec[sector].size(); j++) { if (l_sec[sector][j] == -1) { l_sec[sector][j] = i; indica_secuen = false; //indica que al menos uno de los elementos no tiene secuencia, por lo que hay que planificar todos //TIENE QUE PASARLO A FUERA PARA QUE SI INDICA_SECUEN ES TRUE, NO PLANIFIQUE break; } } } idd=dbf.leeNexRow(); } if(in_amb) { ret=FALSE; goto fin; } olv_limp->nsec=(int)l_sec.size(); //////////////////////////////////////// //inicia los arrays para la sectorización if(!pide_memo_secto()) { sprintf_s(err_str,OLV_MAX_ERR,"Error, Sin memoria para lectura de sectorización"); ret=FALSE; goto fin; } i=-1; int ia=0; //mira cuántos sectores diferentes hay for (std::map>::iterator it=l_sec.begin(); it!=l_sec.end(); ++it) { i++; olv_limp->sec[i].sec_def = it->first; olv_limp->sec[i].namb = (int)it->second.size()-1; olv_limp->sec[i].iamb_ini_def = it->second[0]; for(int ia=1;iasec[i].namb+1;ia++) { olv_limp->sec[i].iamb[ia-1]=it->second[ia]; olv_limp->amb_sec[it->second[ia]].sec = i; } } fin: free(info); if(!ret) { pon_mi_msg("Error en lectura de info de sectorización: %s",err_str); } return ret; } //************************************************************************************* /** * Calcula el número de sectores óptimo para los ámbitos dados */ BOOL Colv_limp_thr::calcula_n_sec() { BOOL ret; int nsec; double cost_tot,cost_sec; //////////////// ret=TRUE; nsec=-1; //////////////// olvlog(LOG_TODO,"olv_limp_t","Comienza cálculo del número de sectores"); pon_mi_progre(OLV_TAREA_CALC_SEC, 0); pon_mi_msg(""); err_str[0]=0; //////////////// olv_limp->nsec =olv_limp->nsec_act = 1; //se fija a un sector para planificar todo junto if(!pide_memo_secto()) { sprintf_s(err_str,OLV_MAX_ERR,"Error, Sin memoria"); ret=FALSE; goto fin; } //hace la sectorización con un sector para que lo asigne por árbol if(!sectoriza_1())//rellena Info_sec { sprintf_s(err_str,OLV_MAX_ERR,"Error en la primera sectorización"); ret=FALSE; goto fin; } //////////////////////////////// //calcula el coste de un sector con todos los ámbitos cost_tot=olv_limp->sec[0].cost_ac;//calcula_cost_1sec_total(olv_limp->n_amb,olv_limp->sec,olv_limp->ias,olv_limp->conjs.n,olv_limp->cost_conj,olv_limp->ang_conj); if(cost_tot>=MAYUSCULO) { sprintf_s(err_str,OLV_MAX_ERR,"Error en el cálculo del coste total de los ámbitos"); ret=FALSE; goto fin; } //calcula el número de sectores, diviendo por el coste máximo de un sector cost_sec = dame_cost_jornada(); if(cost_sec<=0) { sprintf_s(err_str,OLV_MAX_ERR,"Tiempos de jornada, descanso y desplazamiento erróneos"); ret=FALSE; goto fin; } nsec = (int)(cost_tot/cost_sec) + 1; //////////////// olv_limp->calc_nsec=cost_sec; //se indica que el número de sectores es calculado, no impuesto //////////////////////////////// //libera memoria olv_limp->libera_memo_secto(); //pone el número de sectores calculado if(nsec==1) { olv_limp->nsec =olv_limp->nsec_act = nsec; } else { olv_limp->nsec = nsec + 2;//elena abr 2018 coge un margen de 2, excepto si le ha salido que es 1 olv_limp->nsec_act = max(nsec,2); } ///////////////////////////////// fin: if(!ret) { pon_mi_msg("Error en el cálculo del número de sectores: %s",err_str); } return ret; } //************************************************************************************* /** * Calcula el tiempo efectivo de una jornada */ double Colv_limp_thr::dame_cost_jornada() { return olv_limp->t_conv-olv_limp->t_desc; } //************************************************************************************* /** * Lanza la planificación de todos los ámbitos en un sector para calcular el coste total, y lo devuelve * Devuelve también la secuencia de ámbitos planificada */ double Colv_limp_thr::calcula_cost_1sec_total(int n_amb, Info_sec *ss, Djkt_ang_ady *ang_conj) { double coste; int nth,n_sec,i; Secu_amb *ord_sec; th_param_planif thp; BOOL log_debug; BOOL nocalc; //////////////// log_debug=TRUE; n_sec=1; nth=Colv_geom::dame_n_nucleos(); //inicia th memset(&thp, 0, sizeof(thp)); thp.milis_sleep=1; thp.namb_t=n_amb; nocalc=FALSE; coste=0; //////////////// ord_sec=olv_limp->ord_sec; //avisa de progreso olvlog(LOG_TODO,"olv_limp_t","Calculando permutaciones para mejorar al calcular coste de un sector total"); pon_mi_progre(OLV_TAREA_PERMU,0); //////// thp.dth=(th_data_planif*)malloc(sizeof(th_data_planif)*nth); memset(thp.dth, 0, sizeof(th_data_planif)*nth); thp.abs=TRUE; //lanza threads for (i=0; i=0) Sleep(1); } if(!calcula_coste_sectores(ord_sec, ss, n_sec, &thp, FALSE)) { coste=MAYUSCULO; goto salir; } coste=ss[0].cost_ac; salir: //se bloquea y thp.pirate=TRUE; while(thp.nth>0) Sleep(1); if(thp.dth) { if(thp.dth[0].sec) free(thp.dth[0].sec); free(thp.dth); } return coste; } //************************************************************************************* /** * Devuelve la planificación de todos los sectores, en los que calcula la ruta óptima o cercana a la óptima * que recorre los ámbitos de dicho sector */ BOOL Colv_limp_thr::planifica() { olvlog(LOG_TODO,"olv_limp_t","Comienza planificación"); pon_mi_progre(OLV_TAREA_PLANIF, 0); pon_mi_msg(""); err_str[0]=0; //revisa si algún sector no tiene ámbitos int ns=0; for(int i=0;insec;i++) { if(olv_limp->sec[i].namb>0) ns++; } olv_limp->nsec=ns; //inicializa el array de planificaciones olv_limp->plan=(Info_planif*)malloc(olv_limp->nsec*sizeof(Info_planif)); if(!olv_limp->plan) { pon_mi_msg("Error, sin memoria en array de planificación"); return FALSE; } memset(olv_limp->plan,0,olv_limp->nsec*sizeof(Info_planif)); //lanza los threads lanza_subthrs(OLV_LIMP_EV_PLANIFICA_SUB,1); return TRUE; } //************************************************************************************* /** * Devuelve la planificación del sector iésimo, que realiza el thread 'ithr' */ void Colv_limp_thr::planifica_sub_1(int ithr, Matrix2d &cost_amb) { Info_sec *s; Info_amb_sec *aa; int i,iaux,is_ini,is_fin,is_desp,is,jmin; BOOL log_debug=FALSE; BOOL sal,sig; Djkt_nodo *costes_nodos; int nsecu,KK,ic_aux,ss,nsecu2; Secu_amb *secu_ambi=NULL; Param_olv_limp_thr pp; Djkt_nodo* buf_nod=NULL; costes_nodos=NULL; int msecu1, msecu2; msecu1 = msecu2 = olv_limp->conjs.n*2; int *secu,*secu2; secu=(int *)malloc(olv_limp->conjs.n*2*sizeof(int)); if(!secu) { sal=TRUE; goto fin; } buf_nod=olv_limp->arch_dj.dame_buf_nodos(); if(!buf_nod) { sal=TRUE; goto fin; } memset(secu,0,olv_limp->conjs.n*2*sizeof(int)); secu2=(int *)malloc(olv_limp->conjs.n*2*sizeof(int)); if(!secu2) { sal=TRUE; goto fin; } memset(secu2,0,olv_limp->conjs.n*2*sizeof(int)); nsecu2=0; ////////////////////////// pp.id_e=OLV_TAREA_PLANIF;//manda de parámetro la tarea de la que es el progreso ic_aux=0; KK=olv_limp->tipo_ambit; sal=sig=FALSE; jmin=0; prog_subthr=0; aa=olv_limp->amb_sec; iaux=-1; //////////////////////////////////////////////////// //mira a ver cuántos sectores le tocan a este thread if(olv_limp->nsecnsec) { //solo hace un sector, el ithr-esimo is_ini=ithr; is_fin=ithr+1; } else { //no hace ningún sector, no hace falta is_ini=0; is_fin=0; } } else { //hay más sectores que threads, le tocan más de uno is_desp=(int)ceil(1.0*(olv_limp->nsec)/n_subthr); is_ini= min(ithr*is_desp, olv_limp->nsec); is_fin=min((ithr+1)*is_desp,olv_limp->nsec); } ////////////////////////// if(is_fin==is_ini) olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, No Planifica ningún sector", ithr); else if(is_fin-is_ini-1==0) olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sector %02d", ithr,is_ini); else olvlog(LOG_TODO,"olv_limp_t","Subthr %02d, Planifica sectores %02d a %02d", ithr,is_ini, is_fin-1); ////////////////////////// //bucle en todos los sectores que le tocan al thread for(is=is_ini;issec[is]; if(s->namb<=0) continue; s->cost_despl_aux=0; sig=FALSE; //si venía secuencia en el archivo, se utiliza esa if (olv_limp->usa_secuen) { secu_ambi = planifica_sect_dada_secuen(s); if (!secu_ambi) { olvlog(LOG_TODO, "olv_limp_t", "Subthr %ld, Imposible planificar sector %02d", ithr, is); sal = TRUE; continue; } } else { //si no venía, se planifica el sector //busca el ámbito inicial de la planificiación secu_ambi = planifica_sect(s, olv_limp->ang_conj, OLV_LIMP_FACT_PERM); if (!secu_ambi) { olvlog(LOG_TODO, "olv_limp_t", "Subthr %ld, Imposible planificar sector %02d", ithr, is); sal = TRUE; continue; } if (esta_repe(secu_ambi, s->namb)) { olvlog(LOG_TODO, "olv_limp_t", "Esta repe despues de planifica sec"); sal = TRUE; continue; } } /////////////////////////////////////////// //Añade la ruta de la instalación al primer punto if(olv_limp->nod_instal>=0 && olv_limp->ord_sec_plan) { olv_limp->arch_dj.get_b(s->iamb[secu_ambi[0].iamb],secu_ambi[0].entrada,buf_nod); Colv_geom::ruta_dj_inv_ok( olv_limp->nod_instal,//id conjuncion inicial &secu2[0], //puntero a secuencia buf_nod, //nodos djktra conj final olv_limp->conjs.n, &nsecu2); if(!genera_planif_instala(is, 0, 0, nsecu2, secu2, OLV_IDA_INST)) sal=TRUE; } /////////////////////////////////////////// ss=1; s->cost_despl_aux=olv_limp->cost_amb[s->iamb[secu_ambi[0].iamb]][s->iamb[secu_ambi[0].iamb]]; s->cost_despl_aux+=s->t_despl[0];//el desplazamiento de la instalación al primer ámbito secu[0]=olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[0].iamb]).entity()->ref].inod[secu_ambi[0].entrada]; //almacena el coste acumulado aa[s->iamb[secu_ambi[0].iamb]].iseq=0; double cc, cc1=0; for (i=1; inamb; i++) { olv_limp->arch_dj.get_b(s->iamb[secu_ambi[i].iamb],secu_ambi[i].entrada, buf_nod); cc=Colv_geom::ruta_dj_inv_ok( olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[i-1].iamb]).entity()->ref].inod[(secu_ambi[i-1].entrada+1)%2],//id conjuncion final &secu[ss], //puntero a secuencia buf_nod, //nodos djktra conj inicial olv_limp->conjs.n, &nsecu); ss+=nsecu; s->cost_despl_aux+=(float)cc; s->cost_despl_aux+=olv_limp->cost_amb[s->iamb[secu_ambi[i].iamb]][s->iamb[secu_ambi[i].iamb]]; //almacena el coste acumulado aa[s->iamb[secu_ambi[i].iamb]].iseq=i; cc1+=olv_limp->arch_dj.dame_dis(s->iamb[secu_ambi[i-1].iamb],(secu_ambi[i-1].entrada+1)%2,s->iamb[secu_ambi[i].iamb], secu_ambi[i].entrada); ////////////////// if((i%50)==0 || (i==s->namb-1)) { //avisa de progreso olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, amb %ld de %ld", ithr,is, (i+1),(s->namb)); prog_subthr=(1.0*(i+1)/(s->namb))*((is+1)/(is_fin-is_ini)); //porque son varios sectores thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); } ///////////////// } if(olv_limp->tipo_ambit==OLV_AMB_LIN)//añade el coste del último ámbito si es lineal { secu[ss++]=olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[s->namb-1].iamb]).entity()->ref].inod[(secu_ambi[s->namb-1].entrada+1)%2]; } s->cost_despl_aux+=s->t_despl[1];//el desplazamiento del último ámbito a la instalación if(esta_repe(secu_ambi, s->namb, FALSE)) olvlog(LOG_TODO,"olv_limp_t","Esta repe despues de planificar"); olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Planificando sector %02d, coste total %lf",ithr,is,s->cost_despl_aux); /////////////////////////////////////////// //Ruta del último punto a la instalación if(olv_limp->nod_instal>=0 && olv_limp->ord_sec_plan) { Colv_geom::ruta_dj_inv_ok( olv_limp->iaso[olv_limp->carto.get(s->iamb[secu_ambi[s->namb-1].iamb]).entity()->ref].inod[(secu_ambi[s->namb-1].entrada+1)%2], &secu2[0], //puntero a secuencia olv_limp->ord_sec_plan[0].ctnod[0], //nodos djktra conj final olv_limp->conjs.n, &nsecu2); if(!genera_planif_instala(is, 0, 0, nsecu2, secu2, OLV_VUELTA_INST)) { sal=TRUE; break; } } /////////////////////////////////////////// if(!pirate && !sal) { ////////////////////////////////// //genera la ruta y los puntos de control if(!genera_planif(is,s->cost_despl_aux, ss, secu,OLV_PLAN_NORMAL)) sal=TRUE; olv_limp->sec[is].cost_ac=(float)(olv_limp->plan[is].elem[olv_limp->plan[is].nelem-1].coste+olv_limp->sec[is].t_despl[0]+olv_limp->sec[is].t_despl[1]); } ////////////////////////////////// if( secu_ambi) { free(secu_ambi); secu_ambi=NULL; } } free(secu); free(secu2); fin: //Ha terminado, encola al padre olv_limp->arch_dj.libera_buf(buf_nod); if(sal) { prog_subthr=-1;//para avisar al padre de que ha habido un error } thr_padre->encola(OLV_LIMP_EV_PLANIFICA_FIN,NULL,FALSE); } //************************************************************************************* /** * Finaliza y centraliza tareas de planificar, cuando han acabado todos los threads */ BOOL Colv_limp_thr::planifica_fin() { //para los threads para_subthrs(); err_str[0]=0; /////////////////////////////////////// //Si es barrido mixto hay que copiar la info en las que no se ha sectorizado if(olv_limp->barr_mix) copia_info_barr_mix(); /////////////////////////////////// //prepara los datos para guardarlos if(!genera_rut_ctrl(olv_limp->nsec, olv_limp->plan, FALSE)) { pon_mi_msg("Errores en la generación de cartografía con ruta"); return FALSE; } //genera el listado del itinerario if(!genera_list_rut_ctrl()) { pon_mi_msg("Errores en la generación del listado de la ruta: %s",err_str); return FALSE; } //graba a archivo el obg if(!guarda_shp_rut_ctrl()) { pon_mi_msg("Errores en el guardado a shp de la ruta: %s",err_str); return FALSE; } if(!guarda_dbf_sector(2)) { pon_mi_msg("Errores en la generación de información asociada de sector: %s",err_str); return FALSE; } /////////////////////////////////// ///////////////////////////////////////////// //A continuación genera y graba los archivos de los subtramos de cada ruta if(!gen_guard_subtramos()) return FALSE; /////////////////////////////////// olvlog(LOG_TODO,"olv_limp_t","Planificación finalizada"); return TRUE; } //************************************************************************************* /** * Dada la secuencia de las conjunciones que sigue la ruta, genera la ruta diciendo por qué * elementos de la red pasa y coloca los puntos de control */ BOOL Colv_limp_thr::genera_planif(int is, double cost_sec, int nsecu, int *secu, int tip_plan) { int npt_ctrl,ipc; double cost_ctrl; Info_planif *pp; olvlog(LOG_TODO,"olv_limp_t","Almacenando planificación sector %02d",is); ///////////////// ipc=0; npt_ctrl=(olv_limp->npts_ctrl-2); pp=&olv_limp->plan[is]; if(!genera_planif_aux(is,&olv_limp->sec[is], pp, nsecu, secu,tip_plan)) return FALSE; cost_ctrl=pp->elem[pp->nelem-1].coste/(olv_limp->npts_ctrl-2+1); pon_ptos_ctrl(pp, npt_ctrl, cost_ctrl); ////////////////////////////////////////////////////////// /*if (!_CrtCheckMemory()) int i=0;*/ return TRUE; } //************************************************************************************* /** */ void Colv_limp_thr::pon_ptos_ctrl(Info_planif *pp, int npt_ctrl, double cost_ctrl) { double cost_acum; int i, ipc; /////////////////////////////////////////////////////////////// //Inicializa el array de puntos de control pp->pts_ctrl=(Info_planif_ctrl*)malloc((olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl)); if(!pp->pts_ctrl) return; memset(pp->pts_ctrl,0,(olv_limp->npts_ctrl-2+1)*sizeof(Info_planif_ctrl)); ipc=0; cost_acum=0; for(i=0;inelem;i++) { ///////////////////////////// cost_acum=pp->elem[i].coste; //mira si toca punto de control if((cost_acum-(ipc)*(cost_ctrl/*+olv_limp->t_desc*/))>(cost_ctrl-1)) { if(ipcpts_ctrl[ipc].ipt=i-1; ipc++; } else ipc=ipc; } } for(i=0;ipts_ctrl[i].ipt<0) pp->pts_ctrl[i].ipt=pp->nelem-1; } } //************************************************************************************* /** * Dada la secuencia de las conjunciones que sigue la ruta, genera la ruta diciendo por qué * elementos de la red pasa y coloca los puntos de control - Función auxiliar */ BOOL Colv_limp_thr::genera_planif_aux(int is, Info_sec *ss, Info_planif *pp, int nsecu, int *secu, int tip_plan) { int nent, ref_j, i, j, dt,npt, amb_j,nelesec,tp,ref_nw,itr,last_pt,k; double cost,cost_perd,ltot,cost_parc_aux; CartoBaseInfoEntity ient; BYTE *ambs_sec; BOOL is_uno,sal,is_descarg,sdire; ////////////////////////////////////////////////////////////////// nent=olv_limp->carto.getNumberEntities(); nelesec=itr=0; cost_parc_aux=0; sal=is_descarg=sdire=FALSE; last_pt=-1; is_uno=FALSE; ref_nw=0; ////////////////////////////////////////////////////////////////// if(nsecu==1) { is_uno=TRUE; nsecu=2; } //Inicializa los arrays de elementos pp->nelem = nsecu-1; //ielem pp->elem=(Info_elem_planif*)malloc(pp->nelem*sizeof(Info_elem_planif)); if(!pp->elem) return FALSE; memset(pp->elem,0,pp->nelem*sizeof(Info_elem_planif)); ////////////////////////////////////////////////////////////////// //si es un único elemento if(is_uno) { //recorre los ámbitos buscándolo for(j=0;jcarto.getEntity(j); if(ient.entity()->type!=CartoBaseTypes::Line) continue; ref_j=ient.entity()->ref; amb_j=olv_limp->iaso[ref_j].iamb; if(secu[0]==olv_limp->iaso[ref_j].inod[0] || secu[0]==olv_limp->iaso[ref_j].inod[1]) break; } if(j>=nent) { return FALSE; } cost=0; if(amb_j>0) { cost=olv_limp->cost_amb[amb_j][amb_j]; } else { amb_j=olv_limp->iaso[olv_limp->iaso[ref_j].refe2].iamb; if(amb_j>0) cost=olv_limp->cost_amb[amb_j][amb_j]; } dt=OLV_TTO; //añade la info del elemento pp->elem[0].refe=ref_j; pp->elem[0].k=0; pp->elem[0].tp = OLV_PLAN_TIP_AMB; pp->elem[0].ref_nw = -1; pp->elem[0].coste = cost; pp->elem[0].ltot = 0; pp->t[dt]=cost; pp->m[dt]=0; pp->m[OLV_TTO_2] = 0; return TRUE; } ////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////// ambs_sec=(BYTE*)malloc(ss->namb); if(!ambs_sec) return FALSE; memset(ambs_sec,0,ss->namb); //bucle para cada conjunción de la secuencia for(i=0;icarto.getEntity(j); if(ient.entity()->type!=CartoBaseTypes::Line) continue; ref_j=ient.entity()->ref; amb_j=olv_limp->iaso[ref_j].iamb; //busca por las conjunciones almacenadas sdire=((secu[i]==olv_limp->iaso[ref_j].inod[0])&& (secu[i+1]==olv_limp->iaso[ref_j].inod[1])); if(sdire || (((secu[i+1]==olv_limp->iaso[ref_j].inod[0])&& (secu[i]==olv_limp->iaso[ref_j].inod[1])))) { break; } } if(j>=nent) { sal=TRUE; continue; } if(amb_j<0 && olv_limp->iaso[ref_j].refe2>=0) { //no es un ámbito amb_j=olv_limp->iaso[olv_limp->iaso[ref_j].refe2].iamb; } if(amb_j<0 && !(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_NW)) { sal=TRUE; continue; } //calcula la longitud npt=ient.getNumberPtos(); ltot = ient.getLong(); cost=olv_limp->cost_conj[secu[i]][secu[i+1]]; dt=OLV_DT_N; ///////////////////////////// //mira a ver si es carretera o amb para poner inw if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB) //es ámbito { ref_nw=olv_limp->inww_amb[amb_j+!sdire*olv_limp->n_amb].refnw; /////////////////////////////////// //si no pertenece a los ámbitos de este sector o ya ha pasado por él, //es que está desplazándose por él, le pone tipo nw for(k=0;knamb;k++) { if(ss->iamb[k]==amb_j) break; } if(k>=ss->namb || ambs_sec[k] || (tip_plan==OLV_PLAN_INST)) { tp=OLV_PLAN_TIP_NW; //es la segunda vez que pasa por ahí dt=OLV_DESP; cost=ltot/olv_limp->v_despl; } else { /////////////////////////////////// if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB_PEAT) tp=OLV_PLAN_TIP_AMB_PEAT; else tp=OLV_PLAN_TIP_AMB; dt=OLV_TTO; ambs_sec[k]=1; } } else if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_SEG_LIN) //es segmento de ámbito { if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_FIN) ref_nw=olv_limp->inww_amb[amb_j+olv_limp->n_amb].refnw; else ref_nw = olv_limp->inww_amb[amb_j].refnw; tp=OLV_PLAN_TIP_SEG_LIN; ltot=0; } else if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_SEG_PUN) { ref_nw = olv_limp->inww_amb[amb_j].refnw; tp=OLV_PLAN_TIP_AMB; ltot=0; if((last_pt==ref_j) || (tip_plan==OLV_PLAN_INST)) { cost=0; tp=OLV_PLAN_TIP_NW; } else { cost=olv_limp->cost_amb[amb_j][amb_j]; last_pt=ref_j; dt=OLV_TTO; } } else if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_PEAT_REP) { tp=OLV_PLAN_TIP_AMB_PEAT_DESP; //en info0 se ha guardado la peatonal original ref_nw=olv_limp->inww_amb[amb_j+!sdire*olv_limp->n_amb].refnw; dt=OLV_DESP; cost=ltot/olv_limp->v_despl; } else//es carretera { ref_nw=ref_j; tp=OLV_PLAN_TIP_NW; dt=OLV_DESP; } //////////////////// if(is_descarg && (tp!=OLV_PLAN_TIP_AMB)) { cost_perd+=cost; cost=ltot=0; } //////////////////// if((ltot==0) && (dt!=OLV_TTO)) cost=0; ////// //calcula coste acumulado if(nelesec>0) cost_parc_aux=pp->elem[nelesec-1].coste; else cost_parc_aux=0; //añade la info del elemento pp->elem[nelesec].refe=ref_j; pp->elem[nelesec].k=!sdire; pp->elem[nelesec].tp = tp; pp->elem[nelesec].ref_nw = ref_nw; pp->elem[nelesec].coste = cost_parc_aux + cost; pp->elem[nelesec].ltot = ltot; pp->elem[nelesec].aux=0; ////////////// if(dtuds_tto == OliviaDef::GeneralDef::OlvTipTtoM2h) && (dt == OLV_TTO)) { pp->m[OLV_TTO_2] += (ltot * olv_limp->iaso[ref_j].inf_l.ancho); pp->m[dt] += ltot; } else pp->m[dt]+=ltot; pp->t[dt]+=cost; } ////////////// if((tip_plan==OLV_PLAN_RECO) && (tp==OLV_PLAN_TIP_AMB)) { pp->elem[nelesec].aux=itr;//marca los tramos if(comprueba_descarg(amb_j)) itr++; if((!is_descarg && comprueba_descarg(amb_j)) || (is_descarg && !comprueba_descarg(amb_j))) { cost_perd=0; is_descarg=!is_descarg; } } ////////////// nelesec++; } if(sal) { free(ambs_sec); return FALSE; } pp->nelem = nelesec; free(ambs_sec); return TRUE; } //************************************************************************************* /** * Comprueba si en este elemento se va a descargar y en ese caso no se cuenta el desplazamiento hasta el siguiente */ BOOL Colv_limp_thr::comprueba_descarg(int iamb) { return FALSE; } //************************************************************************************* /** * Dada la secuencia de las conjunciones que sigue la ruta para ir y volver de la instalación, genera la planificación */ BOOL Colv_limp_thr::genera_planif_instala(int is, int nvaciados, int ini, int fin, int *secu, int tip_viaje) { int i; Info_planif *pp,*pp_insta; Info_sec *ss; ss=&olv_limp->sec[is]; pp=&olv_limp->plan[is]; pp_insta = pp->planif_insta; if(!pp_insta) { //inicializa, sólo la primera vez //cuenta el número de veces que va a vaciar pp->ninsta=2;//inicialmente tiene la ida y la vuelta a la instalación if(nvaciados) pp->ninsta+=nvaciados*2-1; //todos los vaciados son ida y vuelta pp_insta = (Info_planif *)malloc(pp->ninsta*sizeof(Info_planif)); if(!pp_insta) return FALSE; memset(pp_insta,0,pp->ninsta*sizeof(Info_planif)); pp_insta[0].ninsta=OLV_IDA_INST; pp_insta[pp->ninsta-1].ninsta=OLV_VUELTA_INST; pp->planif_insta = pp_insta; } //busca cuál le toca rellenar for(i=0;ininsta;i++) { if(pp_insta[i].nelem==0) break; } if(i>=pp->ninsta) return FALSE; pp_insta[i].ninsta=tip_viaje; if(!genera_planif_aux(is,ss, &pp_insta[i],fin-ini,&secu[ini],OLV_PLAN_INST)) return FALSE; if(tip_viaje==OLV_IDA_INST) olv_limp->sec[is].t_despl[0]=(float)pp_insta[i].elem[pp_insta[i].nelem-1].coste + olv_limp->t_sal; else if(tip_viaje==OLV_VUELTA_INST) olv_limp->sec[is].t_despl[1]=(float)pp_insta[i].elem[pp_insta[i].nelem-1].coste + olv_limp->t_sal; return TRUE; } //************************************************************************************* /** * Dadas las rutas de los sectores, genera la ruta en una única línea en el obg * y en otro coloca los puntos de control */ BOOL Colv_limp_thr::genera_rut_ctrl(int ns, Info_planif *planif, BOOL tramos) { int is, it, nt, ie_ini, ie_fin, i, k, ins, npt,nmax_pts; double long_fl, long_max_fl; BOOL mal; CartoLine lin, lin_fl; CartoPto pt; CartoBaseInfoEntity ient, ient2; Info_planif *pp; //////////////// long_max_fl=15; long_fl=1; nmax_pts=0; mal=FALSE; memset(pt.pt,0,3*sizeof(double)); ///////////////// olvlog(LOG_TODO,"olv_limp_t","Generando lineales de las rutas en obg"); /////////////////////////////////////////////// //Genera el obg de la ruta, un lineal por sector (o varios por sector si hay idas a recogida) for(is=0;istramos[is].size(); for(it=0;ittramos[is][it].ie[0]; ie_fin=olv_limp->tramos[is][it].ie[1]; if(!genera_rut_aux(pp, is, FALSE,ie_ini,ie_fin)) { mal=TRUE; break; } } } else { if(!genera_rut_aux(pp, is, FALSE,0,pp->nelem-1)) { mal=TRUE; break; } for(ins=0;insninsta;ins++) { //solo entra aquí si hay ruta a las instalaciones if(!genera_rut_aux(&pp->planif_insta[ins], is, TRUE,0,pp->planif_insta[ins].nelem-1)) { mal=TRUE; break; } } } } /////////////////////////////////////////////// //Genera el obg de los puntos if(!tramos && !mal) { int ie; int isfin; for(is=0;isnpts_ctrl;i++) { pt.ia= olv_limp->sec[is].sec_def; memset(pt.pt,0,3*sizeof(double)); if(pp->nelem>0) { isfin=0; if(i==0) ie=0; //el punto de control primero está en el primer elemento else if(i==olv_limp->npts_ctrl-1) { ie=pp->nelem-1;//el punto de control último está en el último elemento isfin=1; } else ie=pp->pts_ctrl[i-1].ipt;//los puntos de control intermedios, los que se han calculado ient=olv_limp->carto.getRef(pp->elem[ie].refe); npt=ient.getNumberPtos(); k=(pp->elem[ie].k+isfin)%2; //porque si es el punto de control final, lo tiene que poner al final //del tramo, no al principio memcpy(pt.pt,ient.getPto(k*(npt-1)),3*sizeof(double)); } mal=(!carto_ctrl.add(pt)); } } } if(mal) return FALSE; return TRUE; } //************************************************************************************* /** * Dadas las rutas de los sectores, genera la ruta en una única línea en el obg * y en otro coloca los puntos de control - Función auxiliar */ BOOL Colv_limp_thr::genera_rut_aux(Info_planif *pp, int is, BOOL is_insta, int ie_ini, int ie_fin) { int npt,npt_tot,i,k; double (*pts_lin)[3],(*ptos_par)[3],(*ptos)[3],(*pts_lin_fl)[3]; BOOL mal; CartoLine lin, lin_parc, lin_fl; CartoBaseInfoEntity ient; double d; double ltot, long_max_fl; int nfl; CartoBase *flech, *rut; //para debug CartoBase carto_aux; if(is_insta) { flech = NULL; rut = &carto_inst; } else { flech=&carto_flech; rut =&carto_rut; } //////////////// long_max_fl=5; mal=FALSE; ///////////////// if(pp->nelem==0 && is_insta) return TRUE; if(pp->nelem==0 && !is_insta) npt_tot=2; else { npt_tot=0; //Contar puntos for(i=ie_ini;i<=ie_fin;i++) { ///////////////////////////// npt_tot += olv_limp->carto.getRef(pp->elem[i].refe).getNumberPtos()-1; } npt_tot++; } if(!(lin.pts+=npt_tot))//pide memoria { return FALSE; } pts_lin = lin.pts.ptr; //Añadir puntos for(i=ie_ini;i<=ie_fin;i++) { ient=olv_limp->carto.getRef(pp->elem[i].refe); npt=ient.getNumberPtos(); lin_parc.pts.n=0; ptos=(double (*)[3])ient.getPto(0); ptos_par=NULL; //si es carretera y es de doble sentido, //hace la paralela a una distancia dada para que no se superpongan la ida y la vuelta if((pp->elem[i].tp==OLV_PLAN_TIP_NW) && (olv_limp->iaso[pp->elem[i].refe].flgs & OLV_LIMP_FLG_NW) && !((olv_limp->iaso[pp->elem[i].refe].flgs & OLV_LIMP_FLG_CIRC_NO_DOB))) { d=OLV_DIST_PARALELAS; if(pp->elem[i].k==0) d=d*(-1);//distancia negativa si es sentido contrario Colv_geom::haz_paralela(ptos,npt,d,&ptos_par); ptos=(double (*)[3])ptos_par; } lin_parc.pts.add(ptos,npt); ///////////////////////// //por si hay que darle la vuelta a los puntos if(pp->elem[i].k==1) { lin_parc.invert(); } carto_aux.add(lin_parc); if(!(lin.pts+lin_parc.pts)) { return FALSE; } if(inelem==0 && !is_insta) { lin.addPto(olv_limp->carto.getPto(0)); lin.addPto(olv_limp->carto.getPto(0)); } lin.ia=olv_limp->sec[is].sec_def; if(!rut->add(lin)) { return FALSE; } if(is_insta) return TRUE; ///////////////////// //carto_aux.exportShp("C:\\Proyectos\\Olivia\\Instal\\rut.shp"); ///////////////////// //ahora las flechas lin_fl.pts+=2; lin_fl.pts.n=2; pts_lin_fl = lin_fl.pts.ptr; lin_fl.ia= olv_limp->sec[is].sec_def; if(pp->nelem==0 && !is_insta) { lin_fl.addPto(olv_limp->carto.getPto(0)); lin_fl.addPto(olv_limp->carto.getPto(0)); if(!flech->add(lin_fl)) { return FALSE; } return TRUE; } ///////////////////////////////// //Pone las flechas a lo largo de la línea nfl=0; ltot= lin.getLong(); nfl=(int)(ltot/long_max_fl); for(i=0;iadd(lin_fl)) { break; } } if(iolv->paths.path_res_rut); //cambiaext(path_shp,".shp",""); *(Cdir_manager::extension_archivo(path_shp)-1)=0; strcat_s(path_shp,"_R.shp"); carto_rut.setNameIa(olv_limp->camps.campo_secto); if(!carto_rut.linesExportShp(path_shp)) return FALSE; if(!guarda_cols_ruta(path_shp)) return FALSE; /////////////////////////////////////////////////////// //luego graba los archivos de los puntos de control //graba todos los sectores en un único path strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_pt); //cambiaext(path_shp,".shp",""); *(Cdir_manager::extension_archivo(path_shp)-1)=0; strcat_s(path_shp,"_C.shp"); carto_ctrl.setNameIa(olv_limp->camps.campo_secto); if(!carto_ctrl.ptosExportShp(path_shp)) return FALSE; if(!guarda_cols_ctrl(path_shp)) return FALSE; ///////////////////////////////////////////// //A continuación graba los archivos de las flechas strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); //cambiaext(path_shp,".shp",""); *(Cdir_manager::extension_archivo(path_shp)-1)=0; strcat_s(path_shp,"_Raux.shp"); carto_flech.setNameIa(olv_limp->camps.campo_secto); if(!carto_flech.linesExportShp(path_shp)) return FALSE; ///////////////////////////////////////////// //A continuación graba los archivos de los viajes a las instalaciones if(olv_limp->nod_instal>=0) { strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); //cambiaext(path_shp,".shp",""); *(Cdir_manager::extension_archivo(path_shp)-1)=0; strcat_s(path_shp,"_I.shp"); carto_inst.setNameIa(olv_limp->camps.campo_secto); if(!carto_inst.linesExportShp(path_shp)) return FALSE; if(!guarda_cols_insta(path_shp)) return FALSE; } return TRUE; } //************************************************************************************* /** * Genera y guarda el shp con las rutas en subtramos, para recogida porque se va a descargar */ BOOL Colv_limp_thr::gen_guard_subtramos() { int ntramos=0; char path_shp[MAX_PATH]; //reutiliza los mismos cartos carto_rut.del(); carto_flech.del(); //cuenta tramos cuenta_tramos(); if(!genera_rut_ctrl(olv_limp->nsec, olv_limp->plan, TRUE)) { pon_mi_msg("Errores en la generación de cartografía con ruta de los subtramos"); return FALSE; } rellena_tramos(); if(olv_limp->tipo_shp_viaj==OLV_SHPRUTINST) { int ii=rellena_insta_tramos(); //combina los lineales de cada subtramo con la ida a descargar y la vuelta de descargar anterior if(ii>0 && !combina_rut_insta()) { pon_mi_msg("Errores en la combinación de viajes con viajes a instalación"); return FALSE; } } //graba los archivos de la ruta de los sectores //graba todos los sectores en un único path strcpy_s(path_shp,MAX_PATH,olv_limp->olv->paths.path_res_rut); //cambiaext(path_shp,".shp",""); *(Cdir_manager::extension_archivo(path_shp)-1)=0; strcat_s(path_shp,"_R2.shp"); carto_rut.setNameIa(olv_limp->camps.campo_secto); if(!carto_rut.linesExportShp(path_shp)) { pon_mi_msg("Errores en el guardado del shp de la capa de viajes"); return FALSE; } if(!guarda_cols_ruta_tram(path_shp)) { pon_mi_msg("Errores al guardar las columnas de la capa de viajes"); return FALSE; } //guarda en los ámbitos una columna de "tramo al que pertenecen" if(!guarda_dbf_sector(3)) { pon_mi_msg("Errores al guardar la columna de viaje de cada cont"); return FALSE; } delete [] olv_limp->tramos; olv_limp->tramos=NULL; return TRUE; }//************************************************************************************* /** * Como los viajes a instalaciones están ordenados, y los tramos también * le corresponde a cada tramo it el viaje it y el it+1, excepto al último, que le pueden * corresponder 3 viajes si la instalación y la descarga no son en el mismo sitio * Además, actualiza el tiempo de los tramos */ int Colv_limp_thr::rellena_insta_tramos() { int it, nt, nins,ii; Info_planif *pinsta; Info_tramos *tramo; ii=0; //para saber si hace algún tramo o no for(int is=0;isnsec;is++) { nt=(int)olv_limp->tramos[is].size(); nins = olv_limp->plan[is].ninsta; if(!nins) continue; if(olv_limp->plan[is].planif_insta[nins-1].nelem==0) nins--; //es porque la descarga y planta son la misma pinsta = olv_limp->plan[is].planif_insta; for(it=0;it< nt;it++) { tramo = &olv_limp->tramos[is][it]; tramo->iins[0]=2*it; tramo->iins[1]=2*it+1; /////////////////////////////////////// //Actualiza los tiempos del tramo sumando los tiempos del viaje a inst tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem-1].coste; tramo->t_fin += (float)pinsta[tramo->iins[1]].elem[pinsta[tramo->iins[1]].nelem-1].coste; tramo->t_total_tr=(float) (tramo->t_fin-tramo->t_ini); tramo->long_tr += pinsta[tramo->iins[0]].m[OLV_DESP] + pinsta[tramo->iins[1]].m[OLV_DESP]; } if (nins % 2) //instala y descarga distintos si es impar { //para el último tramo tramo = &olv_limp->tramos[is][nt-1]; //tramo->iins[0] = 2 * it; tramo->iins[1] = nins - 1; //tramo->t_ini -= (float)pinsta[tramo->iins[0]].elem[pinsta[tramo->iins[0]].nelem - 1].coste; tramo->t_fin += (float)pinsta[tramo->iins[1]].elem[pinsta[tramo->iins[1]].nelem - 1].coste; tramo->t_total_tr = (float)(tramo->t_fin - tramo->t_ini); tramo->long_tr += pinsta[tramo->iins[1]].m[OLV_DESP]; } ii++; } return ii; } //************************************************************************************* /** * Añade las columnas de información a la ruta, tiempos, longitudes, y demás */ BOOL Colv_limp_thr::guarda_cols_ruta_tram(char *path_shp) { char *info; char path_dbf[MAX_PATH]; double tt; int h,m,s; int i, it,ntram,nt,nt_parc; ManagerDbfGdataTable dbfmgr; GdataTable db; //cuenta el número de sectores no vacíos ntram=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; ntram+=(int)olv_limp->tramos[i].size(); } //añade una columna a la ruta de tiempo de ruta strcpy_s(path_dbf,MAX_PATH,path_shp); //cambiaext(path_dbf,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); info = (char *)malloc(ntram* OLV_SHP_SZ_CAMP_SZ); if(!info) { return FALSE; } memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ); AddColsDbf dataDbf(info); if (!dbfmgr.LeeDbf(path_dbf, &db)) { free(info); return FALSE; } //SECTOR ya viene //TRATAMIENTO nt_parc=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;itnomb_tto); } nt_parc+=nt; } if(!dbfmgr.AddCol(NULL,"TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ); //VIAJE nt_parc=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;itnsec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;ittramos[i][it].t_ini; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); } nt_parc+=nt; } if(!dbfmgr.AddCol(NULL,"H_INI",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ); //H_FIN nt_parc=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;ittramos[i][it].t_fin; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); } nt_parc+=nt; } if(!dbfmgr.AddCol(NULL,"H_FIN",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ); //T_TOTAL nt_parc=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;ittramos[i][it].t_total_tr;//tramos[i][it].t_fin-tramos[i][it].t_ini; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); } nt_parc+=nt; } if(!dbfmgr.AddCol(NULL,"T_TOTAL",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ); //M_TOTAL nt_parc = 0; for (i = 0; i < olv_limp->nsec; i++) { if (olv_limp->sec[i].namb == 0) continue; nt = (int)olv_limp->tramos[i].size(); for (it = 0; it < nt; it++) { tt = olv_limp->tramos[i][it].long_tr; //para guardar en número ((double*)info)[nt_parc + it] = tt; } nt_parc += nt; } if (!dbfmgr.AddCol(NULL, "M_TOTAL", GdataTable::Tdouble, &dataDbf)) { free(info); return FALSE; } memset(info, 0, ntram* OLV_SHP_SZ_CAMP_SZ); //T_TTO nt_parc=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; nt=(int)olv_limp->tramos[i].size(); for(it=0;ittramos[i][it].t_tto_tr; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[(nt_parc+it)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); } nt_parc+=nt; } if(!dbfmgr.AddCol(NULL,"T_TRAT",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,ntram* OLV_SHP_SZ_CAMP_SZ); free(info); if (!dbfmgr.grabaDbf(path_dbf, &db)) { return FALSE; } return TRUE; } //************************************************************************************* /** * Cuenta los tramos que hay en la ruta del sector is, si va varias veces a descargar */ void Colv_limp_thr::cuenta_tramos() { olv_limp->tramos = new std::vector[olv_limp->nsec]; Info_planif *pp; Info_tramos tramo; int ie,ii,ilast,iamb; memset(&tramo,0,sizeof(Info_tramos)); tramo.iins[0]=tramo.iins[1]=-1; for(int is=0;isnsec;is++) { pp=&olv_limp->plan[is]; ii=0; tramo.ie[0]=0; for(ie=0;ienelem;ie++) { if(pp->elem[ie].tp!=OLV_PLAN_TIP_AMB) continue; if(pp->elem[ie].aux!=ii) { tramo.ie[1]=ilast; olv_limp->tramos[is].push_back(tramo); ii++; tramo.ie[0]=ie; } if(olv_limp->iaso[pp->elem[ie].refe].flgs & OLV_LIMP_FLG_SEG_PUN) iamb=olv_limp->iaso[pp->elem[ie].refe].refe2; else iamb=olv_limp->iaso[pp->elem[ie].refe].iamb; olv_limp->amb_sec[iamb].res=ii; //marca el tramo en el array de ambitos ilast=ie; } tramo.ie[1]=pp->nelem-1; olv_limp->tramos[is].push_back(tramo); } } //************************************************************************************* /** * Rellena la info de los tramos */ void Colv_limp_thr::rellena_tramos() { Info_planif *pp; Info_tramos *tramo; int ie,it,nt; for(int is=0;isnsec;is++) { pp=&olv_limp->plan[is]; nt=(int)olv_limp->tramos[is].size(); for(it=0;ittramos[is][it]; tramo->namb=0; tramo->ncont=0; for(ie=tramo->ie[0]; ie<=tramo->ie[1];ie++) { tramo->long_tr+=(float) pp->elem[ie].ltot; if(pp->elem[ie].tp!=OLV_PLAN_TIP_AMB) continue; tramo->namb++; } tramo->t_tto_tr = (float)(pp->t[OLV_TTO]); //actualiza tiempos de tramos if (pp->planif_insta) { tramo->t_ini = (float)(pp->planif_insta[2 * it].t[OLV_TTO] + pp->planif_insta[2 * it].elem[pp->planif_insta[2 * it].nelem - 1].coste); tramo->t_fin = (float)pp->planif_insta[2 * it + 1].t[OLV_TTO]; } else { tramo->t_ini = (float)olv_limp->t_ini; tramo->t_fin = (float)(tramo->t_ini + olv_limp->sec[is].cost_ac + olv_limp->t_desc); } tramo->t_total_tr = (float) (tramo->t_fin-tramo->t_ini); } } } //************************************************************************************* /** * Dadas las rutas de los sectores, genera la ruta en una única línea en el obg * y en otro coloca los puntos de control */ BOOL Colv_limp_thr::combina_rut_insta() { //en ob_rut ahora están todos los subtramos en orden: //1 viaje del sector 1, 2 viaje del sector 1, 1 viaje del sector 2, etc //hay que añadir al primer viaje de cada sector la ida desde instalación y la ida a descargar (y la ida a instalación //si es un único viaje) //al resto de viajes intermedios hay que añadirles la vuelta de descargar anterior y la ida a descargar //al último viaje hay que añadirle la ida a descargar y la ida a instalación int is=0, it=0, nt=0, i=0, npt_tot, npt, ntparc,ii; int niparc, res, nmax_pts; BOOL mal = false; Info_planif *planif, *pp; double (*ptos_aux)[3],(*ptos)[3]; CartoLine lin; planif= olv_limp->plan; ntparc=0; niparc=0; nmax_pts=0; for(is=0;isnsec && !mal;is++) { pp=&planif[is]; nt=(int)olv_limp->tramos[is].size(); lin.ia= olv_limp->sec[is].sec_def; lin.pts.n=0; for(it=0;ittramos[is][it].iins[0]; ii<=olv_limp->tramos[is][it].iins[1];ii++) { npt=carto_inst.getEntity(ii+niparc).getNumberPtos(); npt_tot+=npt; res++; } //dado que junta tramos, resta para no replicar los puntos de unión npt_tot=npt_tot-res; //////////////////////////////////////////////////////////////////// //marca para borrar ese tramo carto_rut.remove(it+ntparc); //ya que tiene el total de puntos, actualiza el lineal de ese tramo lin.pts+=npt_tot; ptos_aux=lin.pts.ptr; if(!ptos_aux) { mal=TRUE; continue; } ////////////////////////////////////////////////////////////////////// //ahora copia en ptos_aux los lineales de los tramos que le corresponden for(ii=olv_limp->tramos[is][it].iins[0]; ii<=olv_limp->tramos[is][it].iins[1];ii++) { npt=carto_inst.getEntity(ii+niparc).getNumberPtos(); ptos = (double (*)[3])carto_inst.getEntity(ii+niparc).getPto(0); //copia el viaje al lineal total lin.pts.add(ptos,npt); lin.pts.n--; //memcpy(ptos_aux[npt_parc],ptos,npt*3*sizeof(double)); //npt_parc+=npt-1; if(ii==olv_limp->tramos[is][it].iins[1]) lin.pts.n++; if(ii==olv_limp->tramos[is][it].iins[0]) { //después del primer viaje se copia el tramo de recogida npt=carto_rut.getEntity(it+ntparc).getNumberPtos(); ptos = (double (*)[3])carto_rut.getEntity(it+ntparc).getPto(0); //copia el viaje al lineal total lin.pts.add(ptos,npt); lin.pts.n--; //memcpy(ptos_aux[npt_parc],ptos,npt*3*sizeof(double)); //npt_parc+=npt-1; } } ////////////////////////////////////////////////////////////////////// if(!carto_rut.add(lin)) { mal=TRUE; //entra por aquí?? continue; } } niparc+=ii; //ii apunta a la última instalación del primer sector ntparc+=nt; } if(mal) { return FALSE; } carto_rut.FastClear(); return TRUE; } //************************************************************************************* /** * Añade las columnas de información a la ruta, tiempos, longitudes, y demás */ BOOL Colv_limp_thr::guarda_cols_ruta(char *path_shp) { char *info; char path_dbf[MAX_PATH]; double tt; int h,m,s; char nombia[16]; int nsec, i, isec_novac; ManagerDbfGdataTable dbfmgr; GdataTable db; //cuenta el número de sectores no vacíos nsec=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb!=0) nsec++; } //////////////////////////////////// //El coste_ac es lo mismo que el cost del último elemento de la planif //más el de desplazamientos inicial y final y de descargas //Para el total, hay que añadir los descansos ///////////////////////////////////// //añade una columna a la ruta de tiempo de ruta strcpy_s(path_dbf,MAX_PATH,path_shp); //cambiaext(path_dbf,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); info = (char *)malloc(nsec* OLV_SHP_SZ_CAMP_SZ); if(!info) { return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); AddColsDbf dataDbf(info); if (!dbfmgr.LeeDbf(path_dbf, &db)) { free(info); return FALSE; } //SECTOR ya viene //TRATAMIENTO isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) { continue; } sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%s",olv_limp->nomb_tto); isec_novac++; } if(!dbfmgr.AddCol(NULL,"TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); //rellena la info de hora inicial isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) { continue; } tt=olv_limp->t_ini; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); isec_novac++; } if(!dbfmgr.AddCol(NULL,"H_INI",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); //rellena la info de hora final isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) { continue; } tt=olv_limp->t_ini+ olv_limp->sec[i].cost_ac + olv_limp->t_desc; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); isec_novac++; } if(!dbfmgr.AddCol(NULL,"H_FIN",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); //rellena la info de duración total isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; tt=olv_limp->sec[i].cost_ac+olv_limp->t_desc; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); isec_novac++; } if(!dbfmgr.AddCol(NULL,"T_TOTAL",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); //rellena col m total isec_novac = 0; for (i = 0; i < olv_limp->nsec; i++) { if (olv_limp->sec[i].namb == 0) continue; tt = 0; if ((olv_limp->nod_instal != -1) && (olv_limp->plan[i].ninsta > 0)) { tt = olv_limp->plan[i].planif_insta[0].m[OLV_DESP]; tt += olv_limp->plan[i].planif_insta[olv_limp->plan[i].ninsta - 1].m[OLV_DESP]; } tt += olv_limp->plan[i].m[OLV_DESP] + olv_limp->plan[i].m[OLV_TTO]; //para guardar en número ((double*)info)[isec_novac] = tt; isec_novac++; } if (!dbfmgr.AddCol(NULL, "M_TOTAL", GdataTable::Tdouble, &dataDbf)) { free(info); return FALSE; } memset(info, 0, nsec * OLV_SHP_SZ_CAMP_SZ); //rellena la info de duración de los desplazamientos isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; tt= olv_limp->sec[i].t_despl[0]+olv_limp->sec[i].t_despl[1]; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); isec_novac++; } if(!dbfmgr.AddCol(NULL,"T_INSTA",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); //rellena col m insta isec_novac = 0; for (i = 0; i < olv_limp->nsec; i++) { if (olv_limp->sec[i].namb == 0) continue; if ((olv_limp->nod_instal != -1) && (olv_limp->plan[i].ninsta > 0)) { tt = olv_limp->plan[i].planif_insta[0].m[OLV_DESP]; tt += olv_limp->plan[i].planif_insta[olv_limp->plan[i].ninsta - 1].m[OLV_DESP]; } else tt = 0; //para guardar en número ((double*)info)[isec_novac] = tt; isec_novac++; } if (!dbfmgr.AddCol(NULL, "M_INSTA", GdataTable::Tdouble, &dataDbf)) { free(info); return FALSE; } memset(info, 0, nsec* OLV_SHP_SZ_CAMP_SZ); //rellena la info de duración de los descansos isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; tt=olv_limp->t_desc; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); isec_novac++; } if(!dbfmgr.AddCol(NULL,"T_DESCAN",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); //rellena la info de longitud de la ruta isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; tt=olv_limp->plan[i].m[OLV_DESP]+olv_limp->plan[i].m[OLV_TTO]; //para guardar en número ((double*)info)[isec_novac] = tt; isec_novac++; } if(!dbfmgr.AddCol(NULL,"M_RUTA",GdataTable::Tdouble,&dataDbf)) { free(info); return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); //rellena primero T DESP, M DESP, VELO DESP, T TRAT, M TRAT, VELO/T TRAT int p; int tipodato, sz; tipodato = GdataTable::Tstring; sz = OLV_SHP_SZ_CAMP_CHAR; for(int k=0;k<= OLV_TTO;k++) { for(p=0;p<3;p++) { tt = 0; sz = 0; isec_novac=0; if(p==0) //T { tipodato = GdataTable::Tstring; sz = OLV_SHP_SZ_CAMP_CHAR; strcpy_s(nombia,"T_"); //rellena la info de h for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; tt=olv_limp->plan[i].t[k]; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[isec_novac*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); isec_novac++; } } else if(p==1) //M/M2/UDS { sz = 0; if ((k == OLV_TTO) && (olv_limp->uds_tto == OliviaDef::GeneralDef::OlvTipTtoM2h || olv_limp->uds_tto == OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) { strcpy_s(nombia, "M2_"); for (i = 0; i < olv_limp->nsec; i++) { if (olv_limp->sec[i].namb == 0) continue; tt = olv_limp->plan[i].m[OLV_TTO_2]; //para guardar en número ((double*)info)[isec_novac] = tt; tipodato = GdataTable::Tdouble; isec_novac++; } } else if ((k == OLV_TTO) && (olv_limp->uds_tto == OliviaDef::GeneralDef::OlvTipTtoMin)) { strcpy_s(nombia, "UDS_"); for (i = 0; i < olv_limp->nsec; i++) { if (olv_limp->sec[i].namb == 0) continue; tt = olv_limp->sec[i].namb; //para guardar en número ((int*)info)[isec_novac] = tt; tipodato = GdataTable::Tint; isec_novac++; } } else { strcpy_s(nombia, "M_"); for (i = 0; i < olv_limp->nsec; i++) { if (olv_limp->sec[i].namb == 0) continue; tt = olv_limp->plan[i].m[k]; //para guardar en número ((double*)info)[isec_novac] = tt; tipodato = GdataTable::Tdouble; isec_novac++; } } } else if(p==2) //VELO { if(k==OLV_TTO) { tt=olv_limp->t_tto; if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoM2h_eje) strcpy_s(nombia,"M2_H_"); else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh || olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMh_eje) strcpy_s(nombia,"M_H_"); else if(olv_limp->uds_tto==OliviaDef::GeneralDef::OlvTipTtoMin) { strcpy_s(nombia,"MIN_"); tt=tt/60;//para pasarlo a minutos } } else { strcpy_s(nombia,"KM_H_"); tt=olv_limp->v_despl* OLV_MS2KMH; } for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; if (!tt) { tipodato = GdataTable::Tstring; sz = OLV_SHP_SZ_CAMP_CHAR; sprintf_s(&info[isec_novac * OLV_SHP_SZ_CAMP_CHAR], OLV_SHP_SZ_CAMP_CHAR, "Def. Vias"); } else { //sprintf_s(&info[isec_novac * OLV_SHP_SZ_CAMP_CHAR], OLV_SHP_SZ_CAMP_CHAR, "%.1f", tt); ((double*)info)[isec_novac] = tt; tipodato = GdataTable::Tdouble; sz = 0; } isec_novac++; } } if(k==OLV_TTO) { strcat_s(nombia,"TRAT"); } else if(k==OLV_DESP) { strcat_s(nombia,"DESP"); } if(!dbfmgr.AddCol(NULL,nombia,tipodato,&dataDbf,sz)) { free(info); return FALSE; } memset(info,0,nsec* OLV_SHP_SZ_CAMP_SZ); } } free(info); if (!dbfmgr.grabaDbf(path_dbf, &db)) { return FALSE; } return TRUE; } //************************************************************************************* /** * Añade las columnas de información a los puntos de control */ BOOL Colv_limp_thr::guarda_cols_ctrl(char *path_shp) { char path_dbf[MAX_PATH]; int h,m,s,k; double tt; char *info; int nsec, i, isec_novac; ManagerDbfGdataTable dbfmgr; GdataTable db; //cuenta el número de sectores no vacíos nsec=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb!=0) nsec++; } //añade una columna a los puntos de control de secuencia strcpy_s(path_dbf,MAX_PATH,path_shp); //cambiaext(path_dbf,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); info = (char *)malloc(nsec*olv_limp->npts_ctrl* OLV_SHP_SZ_CAMP_SZ); if(!info) { return FALSE; } memset(info,0,nsec*olv_limp->npts_ctrl* OLV_SHP_SZ_CAMP_SZ); AddColsDbf dataDbf(info); if (!dbfmgr.LeeDbf(path_dbf, &db)) { free(info); return FALSE; } //rellena el nombre del tto k=0; isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,olv_limp->nomb_tto); k++; for(k;k<(isec_novac+1)*olv_limp->npts_ctrl-1;k++) sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,olv_limp->nomb_tto); sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,olv_limp->nomb_tto); isec_novac++; k++; } if(!dbfmgr.AddCol(NULL,"TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,nsec*olv_limp->npts_ctrl* OLV_SHP_SZ_CAMP_SZ); //rellena la info k=0; isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Inicio"); k++; for(k;k<(isec_novac+1)*olv_limp->npts_ctrl-1;k++) sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Medio"); sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"Fin"); isec_novac++; k++; } if(!dbfmgr.AddCol(NULL, olv_limp->camps.campo_secuen,GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,nsec*olv_limp->npts_ctrl* OLV_SHP_SZ_CAMP_SZ); //rellena la info de tiempo k=0; isec_novac=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; tt= olv_limp->t_ini+olv_limp->sec[i].t_despl[0]; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); k++; for(k;k<(isec_novac+1)*olv_limp->npts_ctrl-1;k++) { tt= olv_limp->plan[i].pts_ctrl[k-(isec_novac*olv_limp->npts_ctrl+1)].cost; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); } tt= olv_limp->plan[i].pts_ctrl[olv_limp->npts_ctrl-2].cost; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[k*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); k++; isec_novac++; } if(!dbfmgr.AddCol(NULL,"HORA",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } free(info); if (!dbfmgr.grabaDbf(path_dbf, &db)) { return FALSE; } return TRUE; } //************************************************************************************* /** * Añade las columnas de información a las rutas de viajes a la instalación */ BOOL Colv_limp_thr::guarda_cols_insta(char *path_shp) { char path_dbf[MAX_PATH]; char *info; double tt,ttt; int h,m,s,insta,i,ninsta,ninsta_parc,ninsta_novac; char tray[OLV_SHP_SZ_CAMP_CHAR]; ManagerDbfGdataTable dbfmgr; GdataTable db; //añade una columna strcpy_s(path_dbf,MAX_PATH,path_shp); //cambiaext(path_dbf,".shp",".dbf"); char bufAux[256]; strcpy(path_dbf, Cdir_manager::cambia_extension_archivo(path_dbf,bufAux,".dbf")); //cuenta el número de instalaciones ninsta=0; for(i=0;insec;i++) { for(insta=0;instaplan[i].ninsta;insta++) { if(olv_limp->plan[i].planif_insta[insta].nelem!=0) ninsta++; } } info = (char *)malloc(ninsta* OLV_SHP_SZ_CAMP_SZ); if(!info) { return FALSE; } memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ); AddColsDbf dataDbf(info); if (!dbfmgr.LeeDbf(path_dbf, &db)) { free(info); return FALSE; } //rellena el nombre del tto ninsta_parc=0; for(i=0;insec;i++) { ttt=0; ninsta_novac=0; for(insta=0;instaplan[i].ninsta;insta++) { if(olv_limp->plan[i].planif_insta[insta].nelem==0) continue; sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%s",olv_limp->nomb_tto); ninsta_novac++; } ninsta_parc+=ninsta_novac; } if(!dbfmgr.AddCol(NULL,"TTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ); //rellena la info de tipo de trayecto ninsta_parc=0; for(i=0;insec;i++) { ninsta_novac=0; for(insta=0;instaplan[i].ninsta;insta++) { if(olv_limp->plan[i].planif_insta[insta].nelem==0) continue; switch(olv_limp->plan[i].planif_insta[insta].ninsta) { case OLV_IDA_INST: strcpy_s(tray,"Ida desde instalacion"); //quitado acento para evitar que salga mal break; case OLV_VUELTA_INST: strcpy_s(tray,"Vuelta a instalacion"); break; case OLV_IDA_PLANT_ULT: strcpy_s(tray,"Ultima ida a descargar"); break; case OLV_IDA_PLANT: strcpy_s(tray,"Ida a descargar"); break; case OLV_VUELTA_PLANT: strcpy_s(tray,"Vuelta de descargar"); break; } sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%s",tray); ninsta_novac++; } ninsta_parc+=ninsta_novac; } if(!dbfmgr.AddCol(NULL,"TRAYECTO",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ); //rellena la info de tipo de hora ninsta_parc=0; for(i=0;insec;i++) { ninsta_novac=0; for(insta=0;instaplan[i].ninsta;insta++) { if(olv_limp->plan[i].planif_insta[insta].nelem==0) continue; switch(olv_limp->plan[i].planif_insta[insta].ninsta) { case OLV_IDA_INST: tt=olv_limp->t_ini; break; case OLV_VUELTA_INST: tt=olv_limp->t_ini+olv_limp->sec[i].cost_ac-olv_limp->sec[i].t_despl[1]+olv_limp->t_desc; olv_limp->plan[i].planif_insta[insta].t[OLV_TTO]=tt; break; case OLV_IDA_PLANT: case OLV_IDA_PLANT_ULT: tt=olv_limp->plan[i].planif_insta[insta].t[OLV_TTO]; break; case OLV_VUELTA_PLANT: tt=olv_limp->plan[i].planif_insta[insta].t[OLV_TTO]; break; } dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); ninsta_novac++; } ninsta_parc+=ninsta_novac; } if(!dbfmgr.AddCol(NULL,"H_INI",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ); //rellena la info de duración ninsta_parc=0; for(i=0;insec;i++) { ttt=0; ninsta_novac=0; for(insta=0;instaplan[i].ninsta;insta++) { if(olv_limp->plan[i].planif_insta[insta].nelem==0) continue; tt=olv_limp->plan[i].planif_insta[insta].elem[olv_limp->plan[i].planif_insta[insta].nelem-1].coste; if((olv_limp->plan[i].planif_insta[insta].ninsta== OLV_IDA_INST) || (olv_limp->plan[i].planif_insta[insta].ninsta == OLV_VUELTA_INST) || (olv_limp->plan[i].planif_insta[insta].ninsta == OLV_IDA_PLANT && (insta< olv_limp->plan[i].ninsta-1) && olv_limp->plan[i].planif_insta[insta+1].nelem==0)) tt+= olv_limp->t_sal; ttt+=tt; dame_h_m_s(tt, &h, &m, &s); sprintf_s(&info[(insta+ninsta_parc)*OLV_SHP_SZ_CAMP_CHAR],OLV_SHP_SZ_CAMP_CHAR,"%02d:%02d:%02d h",h,m,s); ninsta_novac++; } ninsta_parc+=ninsta_novac; } if(!dbfmgr.AddCol(NULL,"T_TOTAL",GdataTable::Tstring,&dataDbf,OLV_SHP_SZ_CAMP_CHAR)) { free(info); return FALSE; } memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ); //rellena la info de longitud ninsta_parc=0; for(i=0;insec;i++) { ninsta_novac=0; for(insta=0;instaplan[i].ninsta;insta++) { if(olv_limp->plan[i].planif_insta[insta].nelem==0) continue; tt=olv_limp->plan[i].planif_insta[insta].m[OLV_DESP]; ((double*)info)[insta + ninsta_parc] = tt; ninsta_novac++; } ninsta_parc+=ninsta_novac; } if(!dbfmgr.AddCol(NULL,"M_TOTAL",GdataTable::Tdouble,&dataDbf)) { free(info); return FALSE; } memset(info,0,ninsta* OLV_SHP_SZ_CAMP_SZ); free(info); if (!dbfmgr.grabaDbf(path_dbf, &db)) { return FALSE; } return TRUE; } //************************************************************************************* /** * Recorre la ruta y genera un listado en csv donde guarda las calles por las que va pasando la ruta * El archivo se llama como el shape, concatenando el número de sector y L, en formato csv */ BOOL Colv_limp_thr::genera_list_rut_ctrl() { Info_planif *pp; Colv_csv cc; char tto_desp[32],observ[32],calle[1024],path_csv[MAX_PATH],fila[256],fila0[256]; int i,j,h,m,seg,ii,dt; double ltot,ltot0,tt,t0,linst[2]; BOOL mal; double lttt; linst[0] = linst[1] = 0; mal=FALSE; strcpy_s(path_csv,MAX_PATH,olv_limp->olv->paths.path_data); //cambiaext(path_csv,".shp","_L.csv"); strcpy((Cdir_manager::extension_archivo(path_csv)-1),"_L.csv"); //////////// if(!cc.inicia(path_csv)) { sprintf_s(err_str, "Error al iniciar archivo %s",path_csv); return FALSE; } //Inicia el archivo csv donde va a guardar las calles del itinerario if (olv_limp->uds_tto == OliviaDef::GeneralDef::OlvTipTtoM2h || olv_limp->uds_tto == OliviaDef::GeneralDef::OlvTipTtoM2h_eje) sprintf_s(fila0, 256, "Ruta; Secuencia; Calle; Observaciones; Tratamiento / Desplazamiento; Longitud(m); Tiempo acumulado(h); Tratamiento(m2);\r\n"); else sprintf_s(fila0, 256, "Ruta; Secuencia; Calle; Observaciones; Tratamiento / Desplazamiento; Longitud(m); Tiempo acumulado(h); \r\n"); if(!cc.escribe(fila0)) mal=TRUE; olvlog(LOG_TODO,"olv_limp_t","Escribiendo listados de las rutas en csv"); //graba los listados de la ruta de los sectores for(int s=0; snsec && !mal;s++) { lttt=0; ltot0=0; pp=&olv_limp->plan[s]; if(pp->nelem==0) continue; ii=0; i=0; t0=olv_limp->t_ini + olv_limp->sec[s].t_despl[0]; if ((olv_limp->nod_instal != -1) && (pp->ninsta>0)) { linst[0] = pp->planif_insta[0].m[OLV_DESP]; linst[1] = pp->planif_insta[pp->ninsta-1].m[OLV_DESP]; pp->planif_insta[0].t[OLV_TTO] = olv_limp->t_ini + olv_limp->t_sal; pp->planif_insta[pp->ninsta - 1].t[OLV_TTO] = olv_limp->t_ini + olv_limp->sec[s].cost_ac + olv_limp->t_desc - olv_limp->sec[s].t_despl[1]; } ////////////////////////////////////////////// //primer punto de control e instalación if(i==0) { dame_h_m_s(olv_limp->t_ini, &h, &m, &seg); sprintf_s(fila0, 256, "%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n", s + 1, ii+1, "", "", "Inicio", "", h, m, seg); if (!cc.escribe(fila0)) { mal = TRUE; continue;; } if (linst[0] != 0) { dame_h_m_s(olv_limp->t_ini + olv_limp->t_sal, &h, &m, &seg); sprintf_s(fila0, 256, "%02d;%04d;%s;%s;%s;%.1f;%02d:%02d:%02d;\r\n", s + 1, ii+1, "", "", "Ida desde instalación", linst[0], h, m, seg); if (!cc.escribe(fila0)) { mal = TRUE; continue;; } } dame_h_m_s(t0, &h, &m, &seg); sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii+1,"","","Control - Inicio","",h,m,seg); if(!cc.escribe(fila0)) { mal=TRUE; continue;; } } ////////////////////////////////////////////// for(i=0;inelem;i++) { if(pp->elem[i].tp==OLV_PLAN_TIP_SEG_LIN) goto ctrl; if((pp->elem[i].ltot ==0) && (i>1) && (pp->elem[i].coste==pp->elem[i-1].coste)) continue; if(i<(pp->nelem-1)) { if(((pp->elem[i].ref_nw == pp->elem[i+1].ref_nw) || (((olv_limp->iaso[pp->elem[i].ref_nw].flgs & OLV_LIMP_FLG_NW) && (olv_limp->iaso[pp->elem[i+1].ref_nw].flgs & OLV_LIMP_FLG_NW))&& (strcmp(olv_limp->iaso[pp->elem[i].ref_nw].inf_n.nomb,olv_limp->iaso[pp->elem[i+1].ref_nw].inf_n.nomb)==0))) && (pp->elem[i].tp == pp->elem[i+1].tp) ) { ltot0+=pp->elem[i].ltot; lttt+=pp->elem[i].ltot; goto ctrl; } } strcpy_s(observ,32,""); strcpy_s(tto_desp,32,""); switch(pp->elem[i].tp) { case OLV_PLAN_TIP_NW: strcpy_s(tto_desp,32,"Desplazamiento"); dt=OLV_DESP; break; case OLV_PLAN_TIP_AMB_PEAT_DESP: strcpy_s(tto_desp,32,"Despl. por peatonal"); dt=OLV_DESP; break; case OLV_PLAN_TIP_AMB_PEAT: strcpy_s(observ,32,"Peatonal");//pasa al siguiente para poner tto también case OLV_PLAN_TIP_AMB: case OLV_PLAN_TIP_SEG_PUN: strcpy_s(tto_desp,32,"Tratamiento"); dt=OLV_TTO; ii++; break; case OLV_PLAN_TIP_SEG_LIN: goto ctrl; } if(pp->elem[i].ref_nw>0 && (olv_limp->iaso[pp->elem[i].ref_nw].flgs & OLV_LIMP_FLG_NW) && olv_limp->iaso[pp->elem[i].ref_nw].inf_n.nomb) strcpy_s(calle,1024,olv_limp->iaso[pp->elem[i].ref_nw].inf_n.nomb); else if((pp->elem[i].ref_nw>0) && (!(olv_limp->iaso[pp->elem[i].ref_nw].flgs & OLV_LIMP_FLG_NW)) && (pp->elem[i].tp == OLV_PLAN_TIP_AMB_PEAT)) strcpy_s(calle,1024,"Parque---"); else if ((pp->elem[i].ref_nw > 0) && (olv_limp->iaso[pp->elem[i].ref_nw].flgs & OLV_LIMP_FLG_AMB)) { //apunta a otro ámbito de la red, busca carretera int ref_nw = pp->elem[i].ref_nw; BOOL sdire=false; while ((ref_nw>0) && (olv_limp->iaso[ref_nw].flgs & OLV_LIMP_FLG_AMB)) { ref_nw= olv_limp->inww_amb[ref_nw + !sdire * olv_limp->n_amb].refnw; sdire = !sdire && (olv_limp->tipo_ambit== OLV_AMB_LIN); } if((olv_limp->iaso[ref_nw].flgs & OLV_LIMP_FLG_NW) && olv_limp->iaso[ref_nw].inf_n.nomb) strcpy_s(calle, 1024, olv_limp->iaso[ref_nw].inf_n.nomb); else calle[0] = 0; } else calle[0]=0; tt=pp->elem[i].coste+t0; //a todos los costes de la ruta se añade el tiempo de desplazamiento ltot=ltot0+pp->elem[i].ltot; ltot0=0; lttt+=pp->elem[i].ltot; ////////////////////////////////////////////// //mira si tiene que poner observaciones por si fuera contendor if(((olv_limp->iaso[pp->elem[i].refe].flgs & OLV_LIMP_FLG_SEG_PUN)) && (pp->elem[i].tp==OLV_PLAN_TIP_AMB)) dame_observ_cont(pp->elem[i].refe, observ); ////////////////////////////////////////////// dame_h_m_s(tt, &h, &m, &seg); if((olv_limp->tipo_ambit==OLV_AMB_PUN) && (pp->elem[i].tp==OLV_PLAN_TIP_AMB)) sprintf_s(fila,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,calle,observ,tto_desp,"",h,m,seg); else if(((pp->elem[i].tp == OLV_PLAN_TIP_AMB) || (pp->elem[i].tp == OLV_PLAN_TIP_AMB_PEAT)) && (olv_limp->uds_tto == OliviaDef::GeneralDef::OlvTipTtoM2h || olv_limp->uds_tto == OliviaDef::GeneralDef::OlvTipTtoM2h_eje)) sprintf_s(fila,256,"%02d;%04d;%s;%s;%s;%.1f;%02d:%02d:%02d;%.1f;\r\n",s+1,ii,calle,observ,tto_desp,ltot,h,m,seg,ltot* olv_limp->iaso[pp->elem[i].refe].inf_l.ancho); else sprintf_s(fila, 256, "%02d;%04d;%s;%s;%s;%.1f;%02d:%02d:%02d;\r\n", s + 1, ii, calle, observ, tto_desp, ltot, h, m, seg); ////////////////////////////////////////////// //escribe fila de paso if(!cc.escribe(fila)) { mal=TRUE; continue; } ctrl: ////////////////////////////////////////////// //puntos de control intermedios for(j=0;jnpts_ctrl-2 && !mal;j++) { if(pp->pts_ctrl[j].ipt==i) { t0+=olv_limp->t_desc/(olv_limp->npts_ctrl-2); tt+=olv_limp->t_desc/(olv_limp->npts_ctrl-2); pp->pts_ctrl[j].cost = tt; dame_h_m_s(tt, &h, &m, &seg); sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,"","","Control - Medio","",h,m,seg); if(!cc.escribe(fila0)) { mal=TRUE; continue; } } } ////////////////////////////////////////////// //viajes a vaciar intermedios if((olv_limp->iaso[pp->elem[i].refe].flgs & OLV_LIMP_FLG_SEG_PUN)&& (pp->elem[i].tp==OLV_PLAN_TIP_AMB)) { if(!genera_list_fila_vaci(&cc, fila0,pp->elem[i].refe, s,ii,tt, &t0,FALSE)) { mal=TRUE; break; } } ////////////////////////////////////////////// //ii++; } ////////////////////////////////////////////// //último punto de control e instalación if((i==(pp->nelem))&& !mal) { //quita_t_ult_desc(s,&tt); dame_h_m_s(tt, &h, &m, &seg); sprintf_s(fila0,256,"%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n",s+1,ii,calle,"","Control - Fin","",h,m,seg); if(!cc.escribe(fila0)) { mal=TRUE; continue; } pp->pts_ctrl[olv_limp->npts_ctrl-2].cost = tt; ////////////////////////////////////////////// //último viaje a vaciar if(olv_limp->iaso[pp->elem[i-1].refe].flgs & OLV_LIMP_FLG_SEG_PUN) { if(!genera_list_fila_vaci(&cc, fila0,pp->elem[i-1].refe, s,ii,tt, &t0,TRUE)) { mal=TRUE; break; } tt = t0; } //final ////////////////////////////////////////////// if (linst[1] != 0) { dame_h_m_s(tt, &h, &m, &seg); sprintf_s(fila0, 256, "%02d;%04d;%s;%s;%s;%.1f;%02d:%02d:%02d;\r\n", s + 1, ii, "", "", "Vuelta a instalación", linst[1], h, m, seg); if (!cc.escribe(fila0)) { mal = TRUE; continue; } } tt = olv_limp->t_ini + olv_limp->sec[s].cost_ac + olv_limp->t_desc; ////////////////////////////////////////////// dame_h_m_s(tt, &h, &m, &seg); sprintf_s(fila0, 256, "%02d;%04d;%s;%s;%s;%s;%02d:%02d:%02d;\r\n", s + 1, ii, "", "", "Fin", "", h, m, seg); if(!cc.escribe(fila0)) { mal=TRUE; continue; } } } cc.cierra(); if(mal) { sprintf_s(err_str, "Error al escribir fila en archivo %s",path_csv); return FALSE; } return TRUE; } //************************************************************************************* /** * Quita al tiempo total el del último desplazamiento y la última descarga, solo para reco */ void Colv_limp_thr::quita_t_ult_desc(int s, double *t) { } //************************************************************************************* /** * Añade una línea al listado csv con el viaje a vaciar y vuelta */ void Colv_limp_thr::dame_h_m_s(double tt, int *h_, int *m_, int *s_) { int h,m,s; h=(int)(tt/3600); m=(int)((tt-h*3600)/60); s=(int)(tt-m*60-h*3600); h=h%24; *h_=h; *m_=m; *s_=s; } //************************************************************************************* /** * Añade una línea al listado csv con el viaje a vaciar y vuelta */ BOOL Colv_limp_thr::genera_list_fila_vaci(Colv_csv *cc, char *fila0,int ielem, int s, int ii, double tt, double *t0,BOOL is_fin) { return TRUE; } //************************************************************************************* /** * Añade una columna de observación al listado si es contenedores */ void Colv_limp_thr::dame_observ_cont(int iamb,char *observ) { } //************************************************************************************* /** * Modifica el dbf del shp original para poner la sectorización, * que es el mismo que de entrada con una columna más, * SECTOR (modo 0) o SECUENCIA VACÍA (modo 1) o SECUENCIA BUENA (modo 2) o TRAMO al que pertenece (modo 3) */ BOOL Colv_limp_thr::guarda_dbf_sector(int modo) { char path_dbf[MAX_PATH]; char nom_ia[16]; class AddColS : public IAddColDbf { public: Colv_limp *olv_limp; int mod; int dt; AddColS(Colv_limp *ll, int mod) { this->olv_limp=ll; this->mod=mod; } virtual void setData(int i, void *data) { if(data) { switch(mod) { case 0://sector dt= olv_limp->sec[olv_limp->amb_sec[i].sec].sec_def; break; case 1://secuencia vacía dt=0; break; case 2://secuencia buena dt=olv_limp->amb_sec[i].iseq+1; break; case 3: dt=olv_limp->amb_sec[i].res+1; break; } memcpy(data,(void*)&dt,sizeof(int)); } }; }; AddColS dataDbf(olv_limp,modo); ManagerDbfGdataTable dbfmgr; //primero graba los archivos de la ruta de los sectores //graba todos los sectores en un único path strcpy_s(path_dbf,MAX_PATH,olv_limp->olv->paths.path_data); //cambiaext(path_dbf,".shp",".dbf"); strcpy((Cdir_manager::extension_archivo(path_dbf)),"dbf"); //pone el nombre de la columna if(modo==0)//sector strcpy_s(nom_ia,16, olv_limp->camps.campo_secto); else if((modo==1)|| (modo==2))//secuencia strcpy_s(nom_ia,16, olv_limp->camps.campo_secuen); else if(modo==3) strcpy_s(nom_ia,16,"VIAJE"); if(!dbfmgr.AddCol(path_dbf,nom_ia,GdataTable::Tint,&dataDbf)) { return FALSE; } return TRUE; } //************************************************************************************* /** * Planifica o calcula el orden en el que hay que recorrer los ambitos del sector s * y los nodos de entrada y salida de cada ámbito en caso de ámbito lineal * dada la secuencia que ha leído en la capa */ Secu_amb* Colv_limp_thr::planifica_sect_dada_secuen(Info_sec* s) { Secu_amb* sec; sec = (Secu_amb*)malloc(s->namb * sizeof(Secu_amb)); if (!sec) goto sal; memset(sec, 0, s->namb * sizeof(Secu_amb)); double d = MAYUSCULO, d1 = MAYUSCULO; int nsal, nent; int k, j; int isec; //busca por dónde entra a la secuencia //coge el primer ámbito y busca el nodo más cercano al ámbito siguiente //solo si es de tipo lineal nent = nsal = 0; if (s->namb > 1) { for (k = 0; k < olv_limp->tipo_ambit; k++) { for (j = 0; j < olv_limp->tipo_ambit; j++) { d1 = olv_limp->arch_dj.dame_dis(s->iamb[0], k, s->iamb[1], j); if (d1 < d) { d = d1; nent = j; nsal = k; } } if (d >= MAYUSCULO) return NULL; } sec[1].entrada = nent; sec[1].iamb = 1; sec[1].flags = 1; } sec[0].entrada = (nsal + 1) % 2; sec[0].iamb = 0; sec[0].flags = 1; for (isec = 2; isec < s->namb; isec++) { d = MAYUSCULO; for (j = 0; j < olv_limp->tipo_ambit; j++) { d1 = olv_limp->arch_dj.dame_dis(s->iamb[isec-1], (sec[isec - 1].entrada + 1) % 2, s->iamb[isec], j); if (d1 < d) { d = d1; nent = j; } } if (d >= MAYUSCULO) return NULL; sec[isec].entrada = nent; sec[isec].iamb = isec; sec[isec].flags = 1; } pon_t_desp(s, sec); sal: return sec; } //************************************************************************************* /** * Planifica o calcula el orden en el que hay que recorrer los ambitos del sector s * la idea es partir de una solucion factible (la cual se consigue por distancias minimas) * una vez que se tenga se realizan pequeños cambios en dicho orden para ver si mejora, si es asi se deja dicho cambio como permanente * si no se quita y se intenta otro cambio */ Secu_amb * Colv_limp_thr::planifica_sect(Info_sec *s, Djkt_ang_ady *ang_conj, int npermu) { int i,k, j, nsec; BOOL res=FALSE; BOOL camb; th_param_planif thp; int nth=Colv_geom::dame_n_nucleos(); int obset=0; double ca, cold; Secu_amb *sec; BOOL nocalc=FALSE; sec=(Secu_amb*)malloc(s->namb*sizeof(Secu_amb)); if(!sec) goto sal; memset(sec,0,s->namb*sizeof(Secu_amb)); //prepara arrays---------------------- memset(&thp,0,sizeof(thp)); //copia la info del sector for (i=0; inamb && !pirate; i++) { for(k=0;k<2;k++) { sec[i].ctnod[k]=NULL; } } if(pirate) goto sal; //consigue solucion factible------------------------------ nsec=0; sec[nsec].iamb=dame_planif_iamb_ini(s,olv_limp->cost_amb,&sec[nsec].entrada ); //sec[nsec].entrada=-1; sec[sec[nsec].iamb].flags=1; if(sec[nsec].iamb<0) goto sal; nsec++; while(nsecnamb) { if(!busca_cercano(s,sec, nsec-1, TRUE))//se pilla el minimo local break; nsec++; } if(nsecnamb) goto sal; //mejora solucion--------------------- //prepara thread------------ thp.dth=(th_data_planif*)malloc(sizeof(th_data_planif)*nth); thp.sec=sec; thp.tl=this; thp.namb=s->namb; thp.namb_t=s->namb; thp.s=s; thp.abs=TRUE;//cambio ger if(!thp.dth) goto sigue; thp.dth[0].sec=(Secu_amb *)malloc(s->namb*nth*sizeof(Secu_amb)); if(!thp.dth[0].sec) goto sigue; for (i=1; inamb*i]; //lanza-------------------- for (i=0; i=0) Sleep(1); } ca=dame_coste(sec,0,s->namb-1,s,TRUE); do { thp.modo=2; cold=ca; camb=FALSE; //bucle hasta recorrer todos los elementos de sec //movimientos de elementos puntuales (cambio de posicion) for (i=1; inamb; i++) { thp.param[0]=i; thp.a_currar(); //espera thread while(!thp.terminado()) Sleep(thp.milis_sleep); //elije la mejor permuta j=thp.dame_min(); if(j<0 || ca <=thp.dth[j].coste) continue; cambia_elem(sec, i, thp.dth[j].pos[0], thp.dth[j].pos[1]); ca=thp.dth[j].coste; cold=ca; camb=TRUE; } //permutaciones de npermu elementos /*thp.modo=1; cold=ca; //camb=FALSE; for (i=npermu+obset; inamb; i++) { thp.param[0]=max(i-npermu, obset); thp.param[1]=i; thp.a_currar(); while(!thp.terminado()) Sleep(1); j=thp.dame_min(); if(j<0 || ca <=thp.dth[j].coste || thp.dth[j].pos[0]<0) continue; ca =thp.dth[j].coste; memcpy(sec, thp.dth[j].sec, s->namb*sizeof(Secu_amb)); olvlog(LOG_TODO,"olv_limp_t","Permu Mejora coste de %lf a %lf actu: %lf", cold, ca, dame_coste(sec,0,s->namb-1,ias, s)); cold=ca; camb=TRUE; }*/ } while (camb); thp.milis_sleep=1; //fuera thread thp.pirate=TRUE; while(thp.nth>0) Sleep(1); //---------------------------------------------------------- sigue: if (thp.dth) { if(thp.dth[0].sec) free(thp.dth[0].sec); free(thp.dth); } pon_t_desp(s, sec); res=TRUE; sal: if(!res) { if(sec) free(sec); sec=NULL; } return sec; } //************************************************************************************* /** * Rellena los tiempos de desplazamiento */ void Colv_limp_thr::pon_t_desp(Info_sec *s, Secu_amb *sec) { if((olv_limp->nod_instal>=0) && (s->namb>1)) { s->t_despl[0]=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[sec[0].iamb],sec[0].entrada); s->t_despl[1]=olv_limp->ord_sec_plan[0].ctnod[0][olv_limp->iaso[olv_limp->carto.get(s->iamb[sec[s->namb-1].iamb]).entity()->ref].inod[(sec[s->namb-1].entrada+1)%2]].dis; } } //************************************************************************************* /** * Rellena el siguiente nodo en la secuencia */ BOOL Colv_limp_thr::busca_cercano(Info_sec *s, Secu_amb *sec, int isec, BOOL ind_abs) { double d=MAYUSCULO; int nam, nsal, nent; int k, kk, i, j; int ic, ind_cost; ic=sec[isec].entrada; if(isec==0) isec=isec; if(ic<0) kk=olv_limp->tipo_ambit; else kk=1; for (k=0; knamb; i++) { if(sec[i].flags &1) continue;///ya esta en la secuencia if (ind_abs) ind_cost=s->iamb[i]; else ind_cost=i; for (j=0; jtipo_ambit; j++) { if(d>olv_limp->arch_dj.dame_dis(s->iamb[sec[isec].iamb],ic,s->iamb[i],j)) { d=olv_limp->arch_dj.dame_dis(s->iamb[sec[isec].iamb],ic,s->iamb[i],j); nent=j; nsal=ic; nam=i; } } } } if(d>=MAYUSCULO) return FALSE; sec[isec++].entrada=(nsal+1)%2; sec[isec].entrada=nent; sec[isec].iamb=nam; sec[nam].flags=1; return TRUE; } //************************************************************************************* /** * Da el ámbito inicial por el que empezar la planificación, en función del modo */ short Colv_limp_thr::dame_planif_iamb_ini(Info_sec *s, Matrix2d &cost_amb, short *ent/*=NULL*/) { int i,j,iaux,ient,nn, ref_i, ref_j,k; float aux, dist, dist1; int modo; double a, b,c,d,e; int KK=olv_limp->tipo_ambit; //cost_amb=olv_limp->cost_amb; iaux=-1; modo=3; //////////////////////////////////////////////////// //Coge el ámbito por defecto que se le hubiera dado en la columna secuencia //Si no, busca el ámbito más cercano a la instalación, si la hubiera configurada, //Si no, coge el de mayor coste (modo 1) //O el de 'y+x' menor (modo 2) //O el más alejado del centro (modo 3) if(s->iamb_ini_def!=-1) { ient=0; for(i=0;inamb;i++) { if(s->iamb[i]==s->iamb_ini_def) break; } iaux=i; //busca el nodo más cercano a la instalación, si tiene 2 nodos y hay instalación if(olv_limp->tipo_ambit==OLV_AMB_LIN && olv_limp->nod_instal>=0) { //comprueba los dos nodos dist=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[iaux],ient); dist1=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[iaux],1); if(dist1nod_instal>=0) { aux=(float)MAYUSCULO; //se coge de punto inicial el más cercano a la instalación for(i=0;inamb;i++) { ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; //calcula la distancia de la instalación al inicio del ámbito ient=0; dist=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[i],ient); if(olv_limp->tipo_ambit==OLV_AMB_LIN) { //comprueba los dos nodos dist1=olv_limp->arch_dj.dame_dis(olv_limp->arch_dj.id_instal,0,s->iamb[i],1); if(dist1namb;i++) { ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; //calcula la distancia de mayor entre dos ámbitos for(j=0;jnamb;j++) { if(i==j) continue; ref_j=olv_limp->carto.get(s->iamb[j]).entity()->ref; if(olv_limp->iaso[ref_j].flgs & OLV_LIMP_FLG_AMB_NO) continue; dist=cost_amb[s->iamb[i]][s->iamb[j]]; //busca el mayor if(dist>aux) { aux=dist; iaux=i; } } } } else if(modo==2) { ///////////////////////////////////// ////////////////////// //Como primer ámbito coge el más extremo //el de menor 'y+x' aux=(float)MAYUSCULO; for(i=0;inamb;i++) { ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; if((olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[0]][1]+olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[0]][0])conjs.coor[olv_limp->iaso[ref_i].inod[0]][1]+ olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[0]][0]); iaux=i; } } } else if(modo==3) { ////////////////////// a=0; b=0; c=0; d=0; e=-1; nn=0; //Como primer ámbito coge el más alejado del centro //coge la x y la y media, el centro for(i=0;inamb;i++) { ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; for(k=0;kconjs.coor[olv_limp->iaso[ref_i].inod[k]][1]/1000;//divide para que no haga overflow b+=olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[k]][0]/1000; nn++; } } a=a/nn; b=b/nn; //busca el más alejado de la x e y media for(i=0;inamb;i++) { ref_i=olv_limp->carto.get(s->iamb[i]).entity()->ref; if(olv_limp->iaso[ref_i].flgs & OLV_LIMP_FLG_AMB_NO) continue; for(k=0;kconjs.coor[olv_limp->iaso[ref_i].inod[k]][1]/1000-a; c=fabs(c); d=olv_limp->conjs.coor[olv_limp->iaso[ref_i].inod[k]][0]/1000-b; d=fabs(d); if((c+d)>e) { e=(c+d); iaux=i; if(ent) *ent=k; } } } } return (short)iaux; } //************************************************************************************* /** * Permuta los elementos de sec en sec_out, desde el indice ini hasta fin aplicando la permutacion p-esima */ BOOL Colv_limp_thr::permuta(Secu_amb * sec, int ini, int fin, int p, Secu_amb * sec_out) { int n=fin-ini-1;//numero de elementos a permutar int nn, i, j, k; nn=Colv_geom::fact(n); for (i=ini; i=0) return FALSE;//Error al permutar sec_out[j].flags=1; sec_out[i].entrada=sec[j].entrada; sec_out[i].iamb=sec[j].iamb; } return TRUE; } //************************************************************************************* /** * Cambia de lugar el elemento de la pos_old a la pos_new en la secuencia de elementos sec */ void Colv_limp_thr::cambia_elem( Secu_amb * sec,int pos_old, int pos_new, int entr ) { int i; Secu_amb s; s.entrada=entr; s.iamb=sec[pos_old].iamb; if(pos_old>pos_new) { for (i=pos_old; i>pos_new; i--) { sec[i].entrada=sec[i-1].entrada; sec[i].iamb=sec[i-1].iamb; } } else { for (i=pos_old; isec=ord_sec; thp->tl=this; thp->abs=TRUE; if(!thp->dth[0].sec) thp->dth[0].sec=(Secu_amb *)malloc(thp->namb_t*thp->nth*sizeof(Secu_amb)); if(!thp->dth[0].sec) goto npermu; for (i=1; inth; i++) { thp->dth[i].sec=&thp->dth[0].sec[thp->namb_t*i]; } permu=TRUE; npermu: for (nsecuencia=0; nsecuencianamb; nsecuencia++) ord_sec[nsecuencia].flags =0; nsecuencia=0; if(ss->namb<=0) { ss->cost_ac=0; return TRUE; } //calcula ambito inicial------------ ord_sec[nsecuencia].iamb=dame_planif_iamb_ini(ss,olv_limp->cost_amb, &ord_sec[nsecuencia].entrada); if(ord_sec[nsecuencia].iamb<0) return FALSE; ord_sec[ord_sec[nsecuencia].iamb].flags=1; nsecuencia++; while(nsecuencianamb) { if(!busca_cercano(ss,ord_sec, nsecuencia-1,TRUE))//se pilla el minimo local break; nsecuencia++; } if (nsecuencia>=ss->namb) { ss->cost_ac=(float)dame_coste(ord_sec, 0, ss->namb-1, ss, TRUE); } else return FALSE; //mira a ver si tiene que pertmutar o no. Si un sector tiene casi todos los ámbitos, no se permuta int namb_m, nsec; if(olv_limp->n_amb>=OLV_DESV_MAX_NAMB_MIN) { if(olv_limp->calc_nsec) { if(olv_limp->nsec_act>1) namb_m = olv_limp->n_amb/(olv_limp->nsec_act-1); else namb_m= olv_limp->n_amb; } else namb_m= olv_limp->n_amb/olv_limp->nsec; namb_m+=(int)(namb_m*OLV_DESV_MAX_NAMB); nsec=olv_limp->nsec; if(olv_limp->calc_nsec>0) nsec--; for(int p=0;psec[p].namb>namb_m) { permu=FALSE; break; } } } if(!permu) return TRUE; //mejora solucion--------------------- //prepara thread------------ thp->namb=ss->namb; thp->s=ss; ca=dame_coste(ord_sec, 0, ss->namb-1, ss, TRUE); if(loguear) olvlog(LOG_TODO,"olv_limp_t","coste de partida %lf",ca); do { thp->modo=2; cold=ca; camb=FALSE; //bucle hasta recorrer todos los elementos de sec //movimientos de elementos puntuales (cambio de posicion) for (i=1; inamb; i++) { thp->param[0]=i; thp->a_currar(); //espera thread while(!thp->terminado()) Sleep(thp->milis_sleep); //elije la mejor permuta k=thp->dame_min(); if(loguear && k>=0) olvlog(LOG_TODO,"olv_limp_t","Candidato cal_costes cambia %ld, a %ld, costes: %lf ", i, thp->dth[k].pos[0], thp->dth[k].coste); if(k<0 || ca <=thp->dth[k].coste) continue; cambia_elem(ord_sec, i, thp->dth[k].pos[0], thp->dth[k].pos[1]); ca=thp->dth[k].coste; if(loguear) olvlog(LOG_TODO,"olv_limp_t","Mejora coste cambia %ld, a %ld, costes: %lf a %lf", i, thp->dth[k].pos[0], cold, ca); cold=ca; camb=TRUE; } //permutaciones de npermu elementos /*thp.modo=1; cold=ca; //camb=FALSE; for (i=npermu+obset; inamb; i++) { thp.param[0]=max(i-npermu, obset); thp.param[1]=i; thp.a_currar(); while(!thp.terminado()) Sleep(1); j=thp.dame_min(); if(j<0 || ca <=thp.dth[j].coste || thp.dth[j].pos[0]<0) continue; ca =thp.dth[j].coste; memcpy(sec, thp.dth[j].sec, s->namb*sizeof(Secu_amb)); olvlog(LOG_TODO,"olv_limp_t","Permu Mejora coste de %lf a %lf actu: %lf", cold, ca, dame_coste(sec,0,s->namb-1,ias, s)); cold=ca; camb=TRUE; }*/ } while (camb && !pirate); pon_t_desp(ss, ord_sec); ss->cost_ac=(float)ca; if(loguear) { olvlog(LOG_TODO,"olv_limp_t","Coste %lf",ss->cost_ac); if(esta_repe(thp->sec, thp->namb, FALSE)) olvlog(LOG_TODO,"olv_limp_t","Esta repe en calcula costes"); } return TRUE; //fuera thread /*if(permu) { thp->pirate=TRUE; while(thp->nth>0) Sleep(1); }*/ } //************************************************************************************* /** * Calcula el coste de los sectores mediante planificación de sus ámbitos */ BOOL Colv_limp_thr::calcula_coste_sectores( Secu_amb * ord_sec,Info_sec *ss,int n_sec, th_param_planif *thp, BOOL loguear ) { int obset=0; int i; BOOL res=FALSE; int j; if(!thp) goto npermu; thp->sec=ord_sec; thp->tl=this; thp->abs=TRUE; thp->milis_sleep=0; if(!thp->dth[0].sec) thp->dth[0].sec=(Secu_amb *)malloc(thp->namb_t*thp->nth*sizeof(Secu_amb)); if(!thp->dth[0].sec) goto npermu; for (i=1; inth; i++) { thp->dth[i].sec=&thp->dth[0].sec[thp->namb_t*i]; } npermu: for (j=0; j=n_sec) res=TRUE; thp->milis_sleep=1; return res; } //************************************************************************************* /** * Comprueba si hay elementos repetidos en las permutaciones */ BOOL Colv_limp_thr::esta_repe( Secu_amb *sec, int nsec, BOOL log ) { BOOL res=FALSE; int i; for (i=0; i=0) { olvlog(LOG_TODO,"olv_limp_t","Esta repe la secuencia %ld, en posiciones %ld, %ld ",sec[i].iamb, i, sec[sec[i].iamb].flags); res=TRUE; } sec[sec[i].iamb].flags=i; } return res; } //************************************************************************************* /** * Escribe la info resultado de la planificación */ void Colv_limp_thr::pon_info_resul() { char msg_[OLV_MAX_MSG_PROCE]; char msg_aux[64]; int i,h,m,s; double tt; int nsec=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb!=0) nsec++; } if(olv_limp->olv->modo_ejec==OLV_EJEC_SECT) { //si se ha ejecutado en modo cálculo de sectorización if(olv_limp->calc_nsec>0) { //se ha pedido proponer número de sectores óptimo sprintf_s(msg_,OLV_MAX_MSG_PROCE, "Se ha calculado la sectorización para el número de sectores óptimo\ndada la conf. elegida, que es de %ld, de tiempos:\n", nsec); } else { //se ha impuesto el número de sectores sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Se ha calculado la sectorización para %ld sectores, de tiempos:\n", nsec); } } else if(olv_limp->olv->modo_ejec==OLV_EJEC_PLAN) { sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Se ha calculado la planificación para %ld sectores, de tiempos:\n", nsec); } else if(olv_limp->olv->modo_ejec==OLV_EJEC_TODO) { sprintf_s(msg_,OLV_MAX_MSG_PROCE,"Resultados de todo el proceso para %ld sectores, de tiempos:\n", nsec); } else msg_[0]=0; for(i=0;insec;i++) { if(olv_limp->sec[i].namb==0) continue; tt=olv_limp->sec[i].cost_ac+olv_limp->t_desc; dame_h_m_s(tt, &h, &m, &s); sprintf_s(msg_aux,64,"Sector %ld: %02d:%02d:%02d h, %03d elementos\n",i+1,h,m,s,olv_limp->sec[i].namb); strcat_s(msg_,OLV_MAX_MSG_PROCE,msg_aux); } pon_mi_msg(msg_); pon_mi_progre(tarea,100); } //************************************************************************************* /* * Lanza los multi procesos para el cálculo de cost_amb */ BOOL Colv_limp_thr::lanza_tasks(int nthr_def/*=-1*/) { int nn; char comline[256]; char app_path[MAX_PATH]; char app_path_aux[MAX_PATH]; BOOL ret=TRUE; if(nthr_def>0) nn=nthr_def; else nn=n_subthr; comline[0]=0; app_path[0]=0; app_path_aux[0]=0; olv_limp->olv_tasks->get_dll_dir(app_path_aux); if(!app_path_aux[0]) return FALSE; char *pch=strrchr(app_path_aux,'\\'); if(!pch) return FALSE; *pch=0; sprintf(app_path,"%s\\%s\\%s",app_path_aux,TASKS_FOLDER_NAME,TASKS_APP_NAME); //Arranca los tasks for(int i=0;iolv->olv_sock->ip, TASKS_PORT, i); if(!olv_limp->olv_tasks->lanza_app(app_path, comline)) ret=FALSE; } for(int i=nthr_def;iprog_subthr = 0; for(int i=0;iolv_tasks->inidirs(olv_limp->olv->paths.path_temp); olvlog(LOG_TODO,"olv_limp_t","Guardando matrices"); //lanza los threads lanza_subthrs(OLV_LIMP_EV_GUARD_MATS_SUB); return TRUE; } //************************************************************************************* /* * Cada thread de los que guardan a disco la matriz de dist entre conjunciones y de ángulos */ void Colv_limp_thr::guarda_mats_sub(int ithr) { int nconj,ic; int n_ini, n_desp, n_fin, seg; BOOL mal=FALSE; Param_olv_limp_thr pp; HeadCostConj hd; HeadCostAng hda; //////////////// pp.id_e=OLV_TAREA_GUARD_MAT;//manda de parámetro la tarea de la que es el progreso nconj=olv_limp->conjs.n; //las conjunciones que va a hacer n_desp = (int)ceil(1.0*nconj/n_subthr); n_ini= min(ithr*n_desp, nconj); n_fin = min((ithr+1)*n_desp,nconj); memset(&hd,0,sizeof(HeadCostConj)); memset(&hda,0,sizeof(HeadCostAng)); //////////////// olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Guardando filas de matrices %04d a %04d", ithr,n_ini, n_fin); seg = GetTickCount(); ///////////////////////////////////// //bucle por cada conjunción de la carto Cgarray bufer; for(ic=n_ini; iccost_conj[ic].guarda(hd,ic,olv_limp->olv_tasks->path_cconj,TASKS_EXT_MAT,&bufer)) { mal=TRUE; continue; } if(olv_limp->ang_conj) { if(!olv_limp->ang_conj[ic].guarda(hda,ic,olv_limp->olv_tasks->path_ang, TASKS_EXT_MAT)) { mal=TRUE; continue; } } //avisa de progreso if(((ic-n_ini)%500==0) || ((ic-n_ini)==(n_desp-1))) { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Guardando matrices, %ld de %ld", ithr, (ic-n_ini+1),n_desp); //avisa de progreso prog_subthr=(1.0*(ic-n_ini+1)/n_desp);/// thr_padre->encola(OLV_LIMP_EV_SUBTHR_PROG,&pp,FALSE); } } if(mal) goto va_mal; va_mal: if(mal) { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Error en guardado de matrices", ithr); prog_subthr=-1;//para avisar al padre de que ha habido un error } else { olvlog(LOG_TODO,"olv_limp_t","Subthr %ld, Fin guardado matriz, %.3f seg", ithr, 1.0*(GetTickCount()-seg)/1000); } thr_padre->encola(OLV_LIMP_EV_GUARD_MATS_FIN,NULL,FALSE); } //************************************************************************************* /* * Cada thread de los que guardan a disco la matriz de dist entre conjunciones y de ángulos */ BOOL Colv_limp_thr::guarda_mats_fin() { //////////////// //para los threads para_subthrs(); //guarda matriz de info aso guarda_iaso(); olvlog(LOG_TODO,"olv_limp_t","Guardada matriz de info aso"); //libera esta memoria que ya no le hace falta olv_limp->tip_conj.clear(); olvlog(LOG_TODO,"olv_limp_t","FIN Guardado Matrices"); return TRUE; } //************************************************************************************* /* * Guarda los ic de la info aso del ámbito ia */ BOOL Colv_limp_thr::guarda_iaso() { HANDLE hfile = INVALID_HANDLE_VALUE; int nb, i, ref_i; HeadInfoAso hd; //crea archivo----------------------------------- hfile = CreateFile(olv_limp->olv_tasks->file_iaso, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (hfile == INVALID_HANDLE_VALUE) { i=GetLastError(); return FALSE; } memset(&hd,0,sizeof(HeadInfoAso)); hd.nint=olv_limp->n_amb*3; //graba cabecera------------ nb = sizeof(hd); //calcula el nb if (nb != _lwrite((int)hfile, (LPCCH)&hd, nb)) { goto va_mal; } nb=sizeof(int); //se embucla en los ámbitos guardando sus flags ic[0] e ic[1] for(i=0;in_amb;i++) { ref_i=olv_limp->carto.get(i).entity()->ref; if (nb != _lwrite((int)hfile, (LPCCH)&olv_limp->iaso[ref_i].inod[0], nb)) break; if (nb != _lwrite((int)hfile, (LPCCH)&olv_limp->iaso[ref_i].inod[1], nb)) break; if (nb != _lwrite((int)hfile, (LPCCH)&olv_limp->iaso[ref_i].flgs, nb)) break; } if(in_amb) goto va_mal; CloseHandle(hfile); return TRUE; va_mal: CloseHandle(hfile); return FALSE; } //************************************************************************************* void Colv_limp_thr::ini_infotask(int ntasks) { InfoIniTask ii; memset(&ii,0,sizeof(InfoIniTask)); ii.KK = olv_limp->tipo_ambit; ii.n = olv_limp->conjs.n; ii.namb = olv_limp->n_amb; ii.nthr=n_subthr; ii.ntsks=ntasks; ii.usa_angs = (olv_limp->ang_conj!=NULL); ii.id_instal = olv_limp->nod_instal; ii.id_planta = olv_limp->nod_plant; strcpy_s(ii.path_temp,MAX_PATH,olv_limp->olv_tasks->path_temp); strcpy_s(ii.path_cconj,MAX_PATH,olv_limp->olv_tasks->path_cconj); strcpy_s(ii.path_costamb,MAX_PATH,olv_limp->olv_tasks->path_costamb); strcpy_s(ii.path_ang,MAX_PATH,olv_limp->olv_tasks->path_ang); strcpy_s(ii.file_iaso,MAX_PATH,olv_limp->olv_tasks->file_iaso); strcpy_s(ii.ext,8,TASKS_EXT_MAT); memcpy(&olv_limp->olv->infotask,&ii,sizeof(InfoIniTask)); } //************************************************************************************* BOOL Colv_limp_thr::task_dj_escucha() { //////////////////////////////////////////////// //lanza las tasks //ejecuta n veces OliviaTasks, cada una va a calcular una parte de la matriz de costes entre ambitos //con sus correspondientes dijkstras y lo va a escribir en disco //antes de eso, se han guardado en disco la matriz (o maps) de costes entre conjunciones y de ángulos entre conjunciones //////////////////////////////////////////////// int ntasks=1; pon_mi_progre(OLV_TAREA_MULTITASK, 0); olvlog(LOG_TODO,"olv_limp_t","Comienza ejecución Multitask"); ini_infotask(ntasks); //lanza la escucha olv_limp->soc = new Csock_svThread(); olv_limp->soc->escucha=olv_limp->olv_tasks; if(!olv_limp->soc->liseningThread(TASKS_PORT,olv_limp->olv->olv_sock->ip)) { goto mal; } ////////////////////////////////////// if(!lanza_tasks(ntasks)) { pon_mi_msg("Error al lanzar multitask para el cálculo de costes entre ámbitos"); return FALSE; } return TRUE; mal: olv_limp->soc->close(); delete olv_limp->soc; olv_limp->soc=NULL; return FALSE; } //************************************************************************************* BOOL Colv_limp_thr::task_dj_fin() { //debe iniciar la matriz cost_amb y leerla lo que han rellenado los tasks, y combinarla return TRUE; } //************************************************************************************* void Colv_limp_thr::borra_temp_files(BOOL todo/*=TRUE*/) { Cdir_manager dm; if(todo) { //borra los archivos de dijkstra dm.borra_archivos(olv_limp->olv->paths.path_temp,EXT_ARCH_DIJ_DEFAULT); } //borra los archivos asociados al multitask dm.borra_archivos(olv_limp->olv->paths.path_temp,TASKS_EXT_MAT,TRUE); dm.borra_archivos(olv_limp->olv->paths.path_temp,TASKS_EXT_DIS,TRUE); } //************************************************************************************* //************************************************************************************* //************************************************************************************* //************************************************************************************* /** * Thread para cálculo multiproceso de la planificación */ UINT th_planificacion(LPVOID pp) { th_param_planif *p=(th_param_planif*)pp; int id_th=p->id_th; int id_curro=p->id_curro; int ini, fin, i, j, entr, entr_m; int mm[2]; double d, dm; p->id_th=-1; while(!p->pirate) { if(id_curro==p->id_curro) { //no curro Sleep(p->milis_sleep); continue; } id_curro=p->id_curro; //ha currar switch(p->modo) { case (0)://cambio de un elemento en la ruta i=p->namb/p->nth; ini=max(i*id_th, 1); if(id_th+1==p->nth) fin=p->namb; else fin=ini+i; i=-1; dm=MAYUSCULO; entr=0; while(iniparam[0]) { d=p->tl->dame_coste(p->sec, 0,p->namb-1, p->s, p->abs); } else d=p->tl->dame_coste_ex(p->sec,0,p->namb-1,p->s,p->param[0],ini, entr); if(d=1 || (ini==p->param[0])) { ini++; entr=0; } else entr=1; } p->dth[id_th].coste=dm; p->dth[id_th].pos[0]=i; p->dth[id_th].pos[1]=entr_m; break; case (1)://permutaciones de elementos i=Colv_geom::fact(p->param[1]-p->param[0]); j=i/p->nth; ini=max(i*id_th, 1); if(id_th+1==p->nth) fin=i; else fin=ini+j; i=-1; dm=MAYUSCULO; while(initl->permuta(p->sec, p->param[0], p->param[1], ini, p->dth[id_th].sec)) { ini++; continue; } d=p->tl->dame_coste(p->dth[id_th].sec, 0,p->namb-1, p->s, p->abs); if(dtl->permuta(p->sec, p->param[0], p->param[1], i, p->dth[id_th].sec)) { p->dth[id_th].coste=MAYUSCULO; } else p->dth[id_th].coste=dm; p->dth[id_th].pos[0]=i; break; case (2)://cambio de un elemento en la ruta (cambiandolo de verdad) //pilla un entorno de como mucho +-100 ambitos para las permu //----------------------------------------------- /*i=p->namb/p->nth; ini=max(i*id_th, 1); if(id_th+1==p->nth) fin=p->namb; else fin=ini+i;*/ mm[0]=max(p->param[0]-50,0); mm[1]=min(mm[0]+101,p->namb); i=(mm[1]-mm[0])/p->nth; ini=mm[0]+max(i*id_th, 1); if(id_th+1==p->nth) fin=mm[1]; else fin=ini+i; //----------------------------------------------- i=-1; dm=MAYUSCULO; entr=entr_m=0; while(iniparam[0]) { d=p->tl->dame_coste(p->sec, 0,p->namb-1, p->s, p->abs); } else { memcpy(p->dth[id_th].sec,p->sec, p->namb_t*sizeof(Secu_amb)); p->tl->cambia_elem(p->dth[id_th].sec, p->param[0],ini, entr); d=p->tl->dame_coste(p->dth[id_th].sec, 0,p->namb-1, p->s, p->abs); } if(d=1 || (ini==p->param[0])) { ini++; entr=0; } else entr=1; } p->dth[id_th].coste=dm; p->dth[id_th].pos[0]=i; p->dth[id_th].pos[1]=entr_m; break; default: break; } p->dth[id_th].currando=FALSE; } //salida de thread------------------------- p->dth[id_th].activo=FALSE; lck_sum_atm(&p->nth,-1); return 0; } //************************************************************************************* //************************************************************************************* //************************************************************************************* //************************************************************************************* //************************************************************************************* #endif