/* Programa que faz o casamento do modelo com os dados obtidos. O arquivo de entrada dos vertices deve estar no formato x y z para cada vertice. */ #include #include #include #include #include #define NUM_CASA 3 /* num minimo de vertices casados (dados com modelo transladado) */ #define ERR -1 #define OK 1 #define FALSE 0 #define SIZEX 512 #define SIZEY 512 #define NUM_FACES 3 /* numero de faces incidente em cada vertice */ #define MAXSAIDA 30 float baseline, foco, const_cord_x, const_cord_y; float dist_mod_max; float **mv, /* matriz de vertices do modelo */ **mu_3d, /* matriz de vertices dos dados em 3d */ **mu_iso; /* matriz de vertices dos dados isotropicos */ float **mv_homog; /* mat. para coord. homogeneas dos vertices do modelo*/ float **mv_map_hom, /* vertices do modelo mapeados pela mat final em coord. homogeneas */ **mv_map_iso, /* vertices mv_map_hom em cord. cartezianas isotropicos */ **mat_faces; /* matriz de coeficientes para as faces primeiro indice = indice da face */ float camara_l[3], camara_r[3]; int **mat_ind_face, /* matriz das faces incidentes nos vertices. primeiro ind = vertice, segundo,terceiro = indice da face */ **mat_lig; /* matriz de ligacoes entre vertices */ FILE *saida, *file_log; int nvertice_dados, nvertice_mod, nligacoes; /* num. de vertices obtidos dos dados e do modelo e num de ligacoes */ int num_saida; struct saida_casa{ int ncasados, nvisiveis; float valor, discrepancia, mat_final[4][4]; struct saida_casa *next, *prev; }; struct saida_casa *ini_saida = NULL, /* inicio e fim da lista */ *fim_saida = NULL; /* de saida_casas */ /* --------------------------- funcao para medida de tempo ------------ */ /* now() - retorna uma medida da hora atual em micro segundos */ double now(void) { struct rusage ru; getrusage(RUSAGE_SELF, &ru); return(((double)ru.ru_utime.tv_sec)*1000000.0 + ((double)ru.ru_utime.tv_usec)); } /* ins_vert - insere um novo bloco na lista de blocos saida_casas */ unsigned char ins_saida(ini_lista, fim_lista) struct saida_casa **ini_lista, **fim_lista; { struct saida_casa *ptr, *elemento; ptr = (struct saida_casa *)malloc(sizeof (struct saida_casa)); if(ptr == NULL) return (ERR); if ( ptr == NULL ) return ( ERR ); if ( *ini_lista == NULL ) { *ini_lista = ptr; *fim_lista = ptr; ptr->next = NULL; ptr->prev = NULL; } else { elemento = *fim_lista; elemento->next = ptr; ptr->prev = elemento; ptr->next = NULL; *fim_lista = ptr; } return ( OK ); } /* multiplicacao de vetor linha por matriz em R4 */ void prod_row_mat(x, m, res) float *x, m[4][4], *res; /* x[4], res[4] */ { float s; int j, k; for(j=0; j<4 ;j++) { s = 0.0; for(k=0; k<4 ;k++) { s += x[k]*m[k][j]; } res[j] = s; } } /* multiplicacao de matriz 4x4 por vetor coluna 4x1 */ void prod_mat_colum(a, b, o) /* produto de matrizes o = ab a(4 x 4), b(4 x 1) */ float a[4][4], *b, *o; { int i, j, k; float s; for(k=0; k<4; k++) for(i=0; i<4; i++) { s = 0.0; for(j=0; j<4; j++) { s += a[k][j]*b[j]; } o[k] = s; } } /* determinante de uma matriz 3x3 */ float det3x3(m) float m[3][3]; { float res, d0, d1, d2; d0 = m[1][1]*m[2][2] - m[1][2]*m[2][1]; d1 = m[1][0]*m[2][2] - m[1][2]*m[2][0]; d2 = m[1][0]*m[2][1] - m[1][1]*m[2][0]; res = d0 * m[0][0] - d1 * m[0][1] + d2 * m[0][2]; return(res); } /* cofator do elemento [ix][jx] de uma matriz 4x4 */ float cof(matin, ix, jx) float matin[4][4]; int ix, jx; { float t[3][3]; float res, d; int ii, jj, i, j; ii = 0; for(i=0; i<4; i++) { if(i!=ix) { jj = 0; for(j=0; j<4; j++) { if(j!=jx) { t[ii][jj] = matin[i][j]; jj++; } } ii++; } } d = det3x3(t); if(((ix+jx)%2)!=0) res = -d; else res = d; return(res); } /* determinante de uma matriz 4x4 */ float det4x4(m) float m[4][4]; { float res; res = m[0][0] * cof( m, 0, 0 ) + m[0][1] * cof( m, 0, 1 ) + m[0][2] * cof( m, 0, 2 ) + m[0][3] * cof( m, 0, 3 ); return(res); } /* inversa de uma matriz 4x4 : m * result = I * det(m)**2 */ void inversa(matin, matout) float matin[4][4], matout[4][4]; { float d; int i, j; for(i=0; i<4; i++) for(j=0; j<4; j++) matout[i][j] = 0.0; d = det4x4(matin); if(d == 0.0) return; for(i=0; i<4; i++) for(j=0; j<4; j++) matout[i][j] = cof(matin, j, i)/d; return; } void mat_prod(a, b, o) /* produto de matrizes o = ab a(4 x 4), b(4 x 4) */ float a[4][4], b[4][4], o[4][4]; { int i, j, k; float s; for(k=0; k<4; k++) for(i=0; i<4; i++) { s = 0.0; for(j=0; j<4; j++) { s += a[k][j]*b[j][i]; } o[k][i] = s; } } void crossp(a, b, o) /* produto vetorial o = a x b de vetores R3 */ float *a, *b, *o; { float d; o[0] = a[1]*b[2] - a[2]*b[1]; o[1] = a[2]*b[0] - a[0]*b[2]; o[2] = a[0]*b[1] - a[1]*b[0]; d = sqrt(o[0]*o[0] + o[1]*o[1] + o[2]*o[2]); o[0] /= d; o[1] /= d; o[2] /= d; } float normalize(a) /* calcula o modulo do vetor em R3 */ float *a; { float d; d = sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); a[0] /= d; a[1] /= d; a[2] /= d; return(d); } /* dist() - calcula a distancia entre dois ptos no espaco R3. Retorna a distancia calculada. */ float dist(p1, p2) float *p1, /* ponto 1 ; vetor[3] */ *p2; /* ponto 2 ; vetor[3] */ { int i; float dist = 0.0; /* distancia entre p1 e p2 */ for(i=0; i<3; i++) { dist += (p1[i] - p2[i]) * (p1[i] - p2[i]); } dist = sqrt(dist); return(dist); } /* para visualizar uma matriz */ void ver2(m, nlinhas, ncol) int nlinhas, ncol; float m[nlinhas][ncol]; { int i, j; fprintf(stderr,"\n"); for(i = 0; i0.0 && cam2>0.0) { teste_visib = OK; /* vertice visivel */ break; } } return(teste_visib); } void calculos() { float bar_v[3], bar_u[3]; /* baricentro do modelo e dados */ float trans_mod[4][4], trans_dados[4][4], scal[4][4], /* mat translacao e escala */ aux1[4][4], aux2[4][4], aux1_inv[4][4], /* auxiliares */ rot[4][4], mat_final[4][4]; /* rotacao e final */ float var_v, var_u, alfa; /* variancia dos vert, dados e alfa */ float aux4, aux5, aux3; float vet_aux1[3], vet_aux2[3]; float d, dmin; /* para calculo de distancia */ float quad_dist, discrepancia, valor; int ncasados, nvisiveis; unsigned char teste_visib; float normal_v1[3], normal_v2[3], normal_v3[3];/* normais dos vert.*/ float normal_u1[3], normal_u2[3], normal_u3[3];/* normais dos dados*/ int i, j, k, /* indices utilizados p/ vertices do modelo */ l, m, n; /* indices utilizados p/ vertices dos dados */ int t, h; struct saida_casa *ptr_saida, *ptr_aux; num_saida = 0; for(i=0; i=NUM_CASA) { valor = sqrt(discrepancia/(ncasados + 1)); /* ---------- fprintf(file_log," Ncasados = %d\n Valor = %f\n", ncasados, valor); fprintf(file_log," Discrepancia = %f\n",discrepancia); fprintf(file_log," Vertices usados com modelo = [%d] [%d] [%d]\n",i,j,k); fprintf(file_log," Vertices usados com dados = [%d] [%d] [%d]\n",l,m,n); fprintf(file_log," Matriz trans\n"); ver2(trans,4,4); fprintf(file_log," Matriz Scal\n"); ver2(scal,4,4); fprintf(file_log," Matriz rot\n"); ver2(rot,4,4); fprintf(file_log," Matriz final\n"); ver2(mat_final,4,4); fprintf(file_log," Matriz mu_3d dos dados\n"); ver1(mu_3d,7,3); fprintf(file_log," Matriz mv dos vertices\n"); ver1(mv,8,3); fprintf(file_log," Matriz mv_map_hom[8][4] vertices mapeados\n"); ver1(mv_map_hom,nvertice_mod,4); ------------- */ /* ---- insere na lista saida a matriz final -----*/ if(num_saida >= MAXSAIDA) { ptr_saida = ini_saida; ptr_aux = ptr_saida->next; while(ptr_aux) { if(ptr_aux->discrepancia > ptr_saida->discrepancia) ptr_saida = ptr_aux; ptr_aux = ptr_aux->next; } if(ptr_saida->discrepancia > discrepancia) { ptr_saida->ncasados = ncasados; ptr_saida->nvisiveis = nvisiveis; ptr_saida->valor = valor; ptr_saida->discrepancia = discrepancia; for(h=0; h<4; h++) for(t=0; t<4; t++) ptr_saida->mat_final[h][t] = mat_final[h][t]; } } else { ins_saida(&ini_saida, &fim_saida); num_saida++; ptr_saida = fim_saida; ptr_saida->ncasados = ncasados; ptr_saida->nvisiveis = nvisiveis; ptr_saida->valor = valor; ptr_saida->discrepancia = discrepancia; for(h=0; h<4; h++) for(t=0; t<4; t++) ptr_saida->mat_final[h][t] = mat_final[h][t]; } } } } } /* funcao para ordenar em ordem crescente um vetor de valores e um respectivo vetor de inteiros */ void sort(int n, float value[], int elem[]) { int p, q, r, mx; float cc, vmax; int ccelem; /* 1. Build heap with largest element at value[0] */ for (p = 0; p 0) { q = (r-1) / 2; if (value[q] < cc) { value[r] = value[q]; elem[r] = elem[q]; } else break; r = q; } value[r] = cc; elem[r] = ccelem; } /* 2. Remove elements from heap and insert at end */ for (p = n-1; p > 0; p--) { /* save value[p] */ cc = value[p]; ccelem = elem[p]; /* Move largest heap element to povalue[p] */ value[p] = value[0]; elem[p] = elem[0]; /* Insert cc in remaining heap, from root down */ q = 0; while(1) { value[q] = cc; elem[q] = ccelem; r = 2*q+1; /* Find largest among cc, value[LEFT(q)], value[RIGHT(q)] */ mx = q; vmax = cc; if ((rvmax)) { mx = r; vmax = value[r]; } r++; if((rvmax)) { mx = r; vmax = value[r]; } /* See who won */ if (mx==q) break; /* Promote child and advance */ value[q] = value[mx]; elem[q] = elem[mx]; q = mx; } } } void escreve_saida() { int i, h; struct saida_casa *ptr; float discrepancia, valor; struct saida_casa *vetor_ptr[MAXSAIDA]; int vet_indice[MAXSAIDA]; float value[MAXSAIDA]; i = 0; ptr = ini_saida; while(ptr) { vetor_ptr[i] = ptr; vet_indice[i] = i; value[i] = ptr->discrepancia; i++; ptr = ptr->next; } sort(num_saida, value, vet_indice); /* ordena em ordem crescente de discrepancia */ for(i=0; imat_final, mv_map_hom[h]); /* ESCRITA DOS PTOS MAPEADOS EM ARQUIVO PARA PLOTAGEM EM CANVAS */ fprintf(saida,"%3d %11.4f %11.4f %11.4f %3d %3d %9.4f %9.4f\n",i,mv_map_hom[mat_lig[0][0]][1],mv_map_hom[mat_lig[0][0]][2],mv_map_hom[mat_lig[0][0]][3], vetor_ptr[vet_indice[i]]->ncasados, vetor_ptr[vet_indice[i]]->nvisiveis, vetor_ptr[vet_indice[i]]->discrepancia, vetor_ptr[vet_indice[i]]->valor); fprintf(saida,"%11.4f %11.4f %11.4f\n",mv_map_hom[mat_lig[0][1]][1], mv_map_hom[mat_lig[0][1]] [2],mv_map_hom[mat_lig[0][1]][3]); for(h=1; h