icp.c 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276
  1. /*************************************/
  2. /* Auteur : Rémi Synave */
  3. /* Date de création : 01/03/07 */
  4. /* Date de modification : 15/03/15 */
  5. /* Version : 0.4 */
  6. /*************************************/
  7. /*************************************/
  8. /* Auteur : Romain Leguay */
  9. /* Nguyen Haiduong */
  10. /* Marianne Fichoux */
  11. /* Date de modification : 06/06/09 */
  12. /* Version : 0.2 */
  13. /*************************************/
  14. /***************************************************************************/
  15. /* This file is part of a2ri. */
  16. /* */
  17. /* a2ri is free software: you can redistribute it and/or modify it */
  18. /* under the terms of the GNU Lesser General Public License as published */
  19. /* by the Free Software Foundation, either version 3 of the License, or */
  20. /* (at your option) any later version. */
  21. /* */
  22. /* a2ri is distributed in the hope that it will be useful, */
  23. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  24. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  25. /* GNU Lesser General Public License for more details. */
  26. /* */
  27. /* You should have received a copy of the GNU Lesser General Public */
  28. /* License along with a2ri. */
  29. /* If not, see <http://www.gnu.org/licenses/>. */
  30. /***************************************************************************/
  31. #include "icp.h"
  32. /********** INTERMEDIATE TYPES AND FUNCTIONS **********/
  33. /* Les fonctions intermédiaires sont préfixées de IF */
  34. /* et les types intermédiaires de IT */
  35. typedef struct
  36. {
  37. space_partition *sp;
  38. point3d *liste;
  39. point3d *liste_retour;
  40. int nb;
  41. } ITicp_thread_argument;
  42. void *
  43. IFthread_process_icp_MEC (
  44. void *argu)
  45. {
  46. ITicp_thread_argument *arg = (ITicp_thread_argument *) argu;
  47. point3d p;
  48. double longueur;
  49. for (int i = 0; i < (int) (arg->nb); i++)
  50. {
  51. space_partition_nearest_point (arg->sp, &((arg->liste)[i]), &p, &longueur,
  52. ACCEPT_ZERO_LENGTH);
  53. point3d_init (&(arg->liste_retour[i]), p.x, p.y, p.z);
  54. arg->liste_retour[i].att_int=p.att_int;
  55. }
  56. pthread_exit (0);
  57. }
  58. void
  59. IFmise_en_correspondance (
  60. point3d * data_p,
  61. point3d ** data_x,
  62. const vf_model * const X,
  63. int nbpoint_p,
  64. int *nbpoint_x)
  65. {
  66. //pour chaque point de data_p, nous allons lui associer le point de data_x le plus proche
  67. point3d *listx;
  68. point3d p1,
  69. p2;
  70. space_partition sp;
  71. pthread_t th[A2RI_NB_THREAD];
  72. ITicp_thread_argument argument[A2RI_NB_THREAD];
  73. void *ret[A2RI_NB_THREAD];
  74. point3d_init (&p1, X->xmin, X->ymin, X->zmin);
  75. point3d_init (&p2, X->xmax, X->ymax, X->zmax);
  76. space_partition_new (&sp, &p1, &p2, ((int) pow (X->nbvertex / 24.0, 0.33))+1,
  77. ((int) pow (X->nbvertex / 24.0, 0.33))+1,
  78. ((int) pow (X->nbvertex / 24.0, 0.33))+1);
  79. a2ri_vf_space_partition (X, &sp);
  80. //listx sera la liste final qui remplacera data_x
  81. listx = (point3d *) malloc (nbpoint_p * sizeof (point3d));
  82. a2ri_erreur_critique_si (listx == NULL,
  83. "erreur allocation memoire pour listx\nIFmise_en_correspondance");
  84. for (int i = 0; i < A2RI_NB_THREAD - 1; i++)
  85. {
  86. argument[i].sp = &sp;
  87. argument[i].nb = nbpoint_p / A2RI_NB_THREAD;
  88. argument[i].liste = data_p + i * argument[i].nb;
  89. argument[i].liste_retour = listx + i * argument[i].nb;
  90. }
  91. argument[A2RI_NB_THREAD - 1].sp = &sp;
  92. argument[A2RI_NB_THREAD - 1].nb =
  93. nbpoint_p - (A2RI_NB_THREAD - 1) * (argument[0].nb);
  94. argument[A2RI_NB_THREAD - 1].liste =
  95. data_p + (A2RI_NB_THREAD - 1) * (argument[0].nb);
  96. argument[A2RI_NB_THREAD - 1].liste_retour =
  97. listx + (A2RI_NB_THREAD - 1) * (argument[0].nb);
  98. for (int i = 0; i < A2RI_NB_THREAD; i++)
  99. {
  100. if (pthread_create (th + i, NULL, IFthread_process_icp_MEC, argument + i)
  101. < 0)
  102. {
  103. fprintf (stderr, "pthread_create error for thread 2\n");
  104. exit (1);
  105. }
  106. }
  107. for (int i = 0; i < A2RI_NB_THREAD; i++)
  108. (void) pthread_join (th[i], &ret[i]);
  109. *nbpoint_x = nbpoint_p;
  110. free (*data_x);
  111. *data_x = listx;
  112. space_partition_free (&sp);
  113. }
  114. int
  115. IFsommet_sur_bord(
  116. vf_model *m,
  117. int nbsommet,
  118. hashtable *table)
  119. {
  120. vf_edge *temp;
  121. for(int i=0;i<m->ve[nbsommet].nbincidentvertices;i++)
  122. {
  123. temp=hashtable_look_for(table,nbsommet,m->ve[nbsommet].incidentvertices[i]);
  124. if(temp->nbsharedfaces==1)
  125. return 1;
  126. }
  127. return 0;
  128. }
  129. void
  130. IFmise_en_correspondance_pulli (
  131. vf_model * P,
  132. vf_model * X,
  133. point3d ** data_p,
  134. point3d ** data_x,
  135. int *nbpoint)
  136. {
  137. //pour chaque point de P, nous allons lui associer le point de X le plus proche
  138. point3d p1,
  139. p2,
  140. *listx,*listP;
  141. space_partition sp;
  142. hashtable *tableP=a2ri_vf_construction_edge_table(P,NULL,0);
  143. hashtable *tableX=a2ri_vf_construction_edge_table(X,NULL,0);
  144. pthread_t th[A2RI_NB_THREAD];
  145. ITicp_thread_argument argument[A2RI_NB_THREAD];
  146. void *ret[A2RI_NB_THREAD];
  147. point3d_init (&p1, X->xmin, X->ymin, X->zmin);
  148. point3d_init (&p2, X->xmax, X->ymax, X->zmax);
  149. space_partition_new (&sp, &p1, &p2, ((int) pow (X->nbvertex / 24.0, 0.33))+1,
  150. ((int) pow (X->nbvertex / 24.0, 0.33))+1,
  151. ((int) pow (X->nbvertex / 24.0, 0.33))+1);
  152. a2ri_vf_space_partition (X, &sp);
  153. // listx est la correspondance dans X de chaque sommet de P
  154. listx = (point3d *) malloc (P->nbvertex * sizeof (point3d));
  155. a2ri_erreur_critique_si (listx == NULL,
  156. "erreur allocation memoire pour listx\nIFmise_en_correspondance");
  157. listP=a2ri_vf_to_list_point3d(P);
  158. for (int i = 0; i < A2RI_NB_THREAD - 1; i++)
  159. {
  160. argument[i].sp = &sp;
  161. argument[i].nb = P->nbvertex / A2RI_NB_THREAD;
  162. argument[i].liste = listP + i * argument[i].nb;
  163. argument[i].liste_retour = listx + i * argument[i].nb;
  164. }
  165. argument[A2RI_NB_THREAD - 1].sp = &sp;
  166. argument[A2RI_NB_THREAD - 1].nb =
  167. P->nbvertex - (A2RI_NB_THREAD - 1) * (argument[0].nb);
  168. argument[A2RI_NB_THREAD - 1].liste =
  169. listP + (A2RI_NB_THREAD - 1) * (argument[0].nb);
  170. argument[A2RI_NB_THREAD - 1].liste_retour =
  171. listx + (A2RI_NB_THREAD - 1) * (argument[0].nb);
  172. for (int i = 0; i < A2RI_NB_THREAD; i++)
  173. {
  174. if (pthread_create (th + i, NULL, IFthread_process_icp_MEC, argument + i)
  175. < 0)
  176. {
  177. fprintf (stderr, "pthread_create error for thread 2\n");
  178. exit (1);
  179. }
  180. }
  181. for (int i = 0; i < A2RI_NB_THREAD; i++)
  182. (void) pthread_join (th[i], &ret[i]);
  183. *nbpoint=0;
  184. for(int i=0;i<P->nbvertex;i++)
  185. {
  186. if(!IFsommet_sur_bord(P,i,tableP) && !IFsommet_sur_bord(X,listx[i].att_int,tableX))
  187. {
  188. point3d pt;
  189. point3d_init(&pt,P->ve[i].x,P->ve[i].y,P->ve[i].z);
  190. //printf("%6d - (%9.4lf , %9.4lf , %9.4lf)\n",i,pt.x,pt.y,pt.z);
  191. list_point3d_add(data_p,nbpoint,&pt,WITH_REDUNDANCE);
  192. *nbpoint=*nbpoint-1;
  193. point3d_init(&pt,X->ve[listx[i].att_int].x,X->ve[listx[i].att_int].y,X->ve[listx[i].att_int].z);
  194. //printf("%6d - (%9.4lf , %9.4lf , %9.4lf)\n\n",listx[i].att_int,pt.x,pt.y,pt.z);
  195. list_point3d_add(data_x,nbpoint,&pt,WITH_REDUNDANCE);
  196. }
  197. }
  198. space_partition_free (&sp);
  199. free(listP);
  200. free(listx);
  201. hashtable_free(tableX);
  202. hashtable_free(tableP);
  203. free(tableX);
  204. free(tableP);
  205. }
  206. double
  207. IFcompute_error_nv(
  208. point3d * data_pk,
  209. point3d * data_x,
  210. int nbpoint,
  211. gsl_matrix *rotation,
  212. gsl_matrix *translation)
  213. {
  214. double retour=0.0;
  215. double data[3];
  216. gsl_matrix *pos1,
  217. *pos2;
  218. //rotation
  219. for (int i = 0; i < nbpoint; i++)
  220. {
  221. data[0] = data_pk[i].x;
  222. data[1] = data_pk[i].y;
  223. data[2] = data_pk[i].z;
  224. pos1 = matrix_init (data, 1, 3);
  225. pos2 = matrix_mul (pos1, rotation);
  226. data_pk[i].x = gsl_matrix_get (pos2, 0, 0);
  227. data_pk[i].y = gsl_matrix_get (pos2, 0, 1);
  228. data_pk[i].z = gsl_matrix_get (pos2, 0, 2);
  229. gsl_matrix_free (pos1);
  230. gsl_matrix_free (pos2);
  231. }
  232. //translation
  233. for (int i = 0; i < nbpoint; i++)
  234. {
  235. data[0] = data_pk[i].x;
  236. data[1] = data_pk[i].y;
  237. data[2] = data_pk[i].z;
  238. pos1 = matrix_init (data, 1, 3);
  239. pos2 = matrix_add (pos1, translation);
  240. data_pk[i].x = gsl_matrix_get (pos2, 0, 0);
  241. data_pk[i].y = gsl_matrix_get (pos2, 0, 1);
  242. data_pk[i].z = gsl_matrix_get (pos2, 0, 2);
  243. gsl_matrix_free (pos1);
  244. gsl_matrix_free (pos2);
  245. }
  246. for(int i=0;i<nbpoint;i++)
  247. retour+=point3d_square_length(&(data_pk[i]),&(data_x[i]));
  248. return retour;
  249. }
  250. int IFrejet_etape_tri_rapide (
  251. double *longueur,
  252. int *index,
  253. int min,
  254. int max,
  255. int type)
  256. {
  257. double temp = longueur[max];
  258. int temp_index = index[max];
  259. while (max > min)
  260. {
  261. if (type == ASC)
  262. {
  263. while (max > min && longueur[min] <= temp)
  264. min++;
  265. }
  266. else
  267. {
  268. while (max > min && longueur[min] > temp)
  269. min++;
  270. }
  271. if (max > min)
  272. {
  273. longueur[max] = longueur[min];
  274. index[max] = index[min];
  275. max--;
  276. if (type == ASC)
  277. {
  278. while (max > min && longueur[max] >= temp)
  279. max--;
  280. }
  281. else
  282. {
  283. while (max > min && longueur[max] < temp)
  284. max--;
  285. }
  286. if (max > min)
  287. {
  288. longueur[min] = longueur[max];
  289. index[min] = index[max];
  290. min++;
  291. }
  292. }
  293. }
  294. longueur[max] = temp;
  295. index[max] = temp_index;
  296. return (max);
  297. }
  298. void IFrejet_tri_rapide (
  299. double *longueur,
  300. int *index,
  301. int deb,
  302. int fin,
  303. int type)
  304. {
  305. int mil;
  306. if (deb < fin)
  307. {
  308. mil = IFrejet_etape_tri_rapide (longueur, index, deb, fin, type);
  309. if (mil - deb > fin - mil)
  310. {
  311. IFrejet_tri_rapide (longueur, index, mil + 1, fin, type);
  312. IFrejet_tri_rapide (longueur, index, deb, mil - 1, type);
  313. }
  314. else
  315. {
  316. IFrejet_tri_rapide (longueur, index, deb, mil - 1, type);
  317. IFrejet_tri_rapide (longueur, index, mil + 1, fin, type);
  318. }
  319. }
  320. }
  321. void
  322. IFrejet (
  323. point3d ** data_pk,
  324. point3d ** data_x,
  325. point3d ** data_p,
  326. int *nbpoint,
  327. double recouvrement)
  328. {
  329. int *index = (int *) malloc ((*nbpoint) * sizeof (int));
  330. a2ri_erreur_critique_si (index == NULL,
  331. "erreur allocation memoire pour index\nIFrejet");
  332. double *listelongueur = (double *) malloc ((*nbpoint) * sizeof (double));
  333. a2ri_erreur_critique_si (listelongueur == NULL,
  334. "erreur allocation memoire pour listelongueur\nIFrejet");
  335. point3d *new_data_pk,
  336. *new_data_x,
  337. *new_data_p;
  338. int agarder;
  339. //calcul du nombre de point à garder en fonction du taux de recouvrement
  340. agarder = (*nbpoint) * recouvrement;
  341. point3d p1,
  342. p2;
  343. for (int i = 0; i < (*nbpoint); i++)
  344. {
  345. point3d_init (&p1, (*data_pk)[i].x, (*data_pk)[i].y, (*data_pk)[i].z);
  346. point3d_init (&p2, (*data_x)[i].x, (*data_x)[i].y, (*data_x)[i].z);
  347. listelongueur[i] = point3d_length (&p1, &p2);
  348. index[i] = i;
  349. }
  350. IFrejet_tri_rapide (listelongueur, index, 0, (*nbpoint) - 1, ASC);
  351. new_data_pk = (point3d *) malloc (agarder * sizeof (point3d));
  352. a2ri_erreur_critique_si (new_data_pk == NULL,
  353. "erreur allocation memoire pour new_data_pk\nIFrejet");
  354. new_data_x = (point3d *) malloc (agarder * sizeof (point3d));
  355. a2ri_erreur_critique_si (new_data_x == NULL,
  356. "erreur allocation memoire pour new_data_x\nIFrejet");
  357. new_data_p = (point3d *) malloc (agarder * sizeof (point3d));
  358. a2ri_erreur_critique_si (new_data_p == NULL,
  359. "erreur allocation memoire pour new_data_p\nIFrejet");
  360. //mise à jour des listes de points
  361. for (int i = 0; i < agarder; i++)
  362. {
  363. new_data_pk[i].x = (*data_pk)[index[i]].x;
  364. new_data_pk[i].y = (*data_pk)[index[i]].y;
  365. new_data_pk[i].z = (*data_pk)[index[i]].z;
  366. new_data_x[i].x = (*data_x)[index[i]].x;
  367. new_data_x[i].y = (*data_x)[index[i]].y;
  368. new_data_x[i].z = (*data_x)[index[i]].z;
  369. new_data_p[i].x = (*data_p)[index[i]].x;
  370. new_data_p[i].y = (*data_p)[index[i]].y;
  371. new_data_p[i].z = (*data_p)[index[i]].z;
  372. }
  373. free (index);
  374. free (listelongueur);
  375. free (*data_pk);
  376. free (*data_x);
  377. free (*data_p);
  378. *data_pk = new_data_pk;
  379. *data_x = new_data_x;
  380. *data_p = new_data_p;
  381. *nbpoint = agarder;
  382. }
  383. gsl_matrix *
  384. IFcompute_rotation (
  385. point3d * data_p,
  386. point3d * data_x,
  387. int nbpoint)
  388. {
  389. //voir article de Besl p243
  390. gsl_matrix *Exp,
  391. *A,
  392. *Exptrans,
  393. *delta,
  394. *QExp,
  395. *identity3,
  396. *trExpidentity3,
  397. *basdroite,
  398. *rotation;
  399. double data[3],
  400. trExp,
  401. q0,
  402. q1,
  403. q2,
  404. q3;
  405. gsl_vector *eval = gsl_vector_alloc (4);
  406. a2ri_erreur_critique_si (eval == NULL,
  407. "erreur allocation memoire pour eval\nIFcompute_rotation");
  408. gsl_matrix *evec = gsl_matrix_alloc (4, 4);
  409. a2ri_erreur_critique_si (evec == NULL,
  410. "erreur allocation memoire pour evec\nIFcompute_rotation");
  411. gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc (4);
  412. a2ri_erreur_critique_si (w == NULL,
  413. "erreur allocation memoire pour w\nIFcompute_rotation");
  414. identity3 = gsl_matrix_alloc (3, 3);
  415. a2ri_erreur_critique_si (identity3 == NULL,
  416. "erreur allocation memoire pour identity3\nIFcompute_rotation");
  417. gsl_matrix_set_identity (identity3);
  418. Exp = cross_variance (data_p, data_x, nbpoint);
  419. Exptrans = matrix_transpose (Exp);
  420. A = matrix_sub (Exp, Exptrans);
  421. data[0] = gsl_matrix_get (A, 2, 1);
  422. data[1] = gsl_matrix_get (A, 0, 2);
  423. data[2] = gsl_matrix_get (A, 1, 0);
  424. delta = matrix_init (data, 3, 1);
  425. //trExp signifie trace de la matrice Exp
  426. trExp =
  427. gsl_matrix_get (Exp, 0, 0) + gsl_matrix_get (Exp, 1,
  428. 1) + gsl_matrix_get (Exp, 2,
  429. 2);
  430. trExpidentity3 = matrix_mul_scale (identity3, trExp);
  431. basdroite = matrix_sub (matrix_add (Exp, Exptrans), trExpidentity3);
  432. QExp = gsl_matrix_alloc (4, 4);
  433. a2ri_erreur_critique_si (QExp == NULL,
  434. "erreur allocation memoire pour QExp\nIFcompute_rotation");
  435. gsl_matrix_set (QExp, 0, 0, trExp);
  436. gsl_matrix_set (QExp, 0, 1, gsl_matrix_get (delta, 0, 0));
  437. gsl_matrix_set (QExp, 0, 2, gsl_matrix_get (delta, 1, 0));
  438. gsl_matrix_set (QExp, 0, 3, gsl_matrix_get (delta, 2, 0));
  439. gsl_matrix_set (QExp, 1, 0, gsl_matrix_get (delta, 0, 0));
  440. gsl_matrix_set (QExp, 1, 1, gsl_matrix_get (basdroite, 0, 0));
  441. gsl_matrix_set (QExp, 1, 2, gsl_matrix_get (basdroite, 0, 1));
  442. gsl_matrix_set (QExp, 1, 3, gsl_matrix_get (basdroite, 0, 2));
  443. gsl_matrix_set (QExp, 2, 0, gsl_matrix_get (delta, 1, 0));
  444. gsl_matrix_set (QExp, 2, 1, gsl_matrix_get (basdroite, 1, 0));
  445. gsl_matrix_set (QExp, 2, 2, gsl_matrix_get (basdroite, 1, 1));
  446. gsl_matrix_set (QExp, 2, 3, gsl_matrix_get (basdroite, 1, 2));
  447. gsl_matrix_set (QExp, 3, 0, gsl_matrix_get (delta, 2, 0));
  448. gsl_matrix_set (QExp, 3, 1, gsl_matrix_get (basdroite, 2, 0));
  449. gsl_matrix_set (QExp, 3, 2, gsl_matrix_get (basdroite, 2, 1));
  450. gsl_matrix_set (QExp, 3, 3, gsl_matrix_get (basdroite, 2, 2));
  451. gsl_eigen_symmv (QExp, eval, evec, w);
  452. gsl_eigen_symmv_free (w);
  453. //extraction des valeurs maximales propres de la matrics QExp
  454. int index = 0;
  455. if (gsl_vector_get (eval, 1) > gsl_vector_get (eval, index))
  456. index = 1;
  457. if (gsl_vector_get (eval, 2) > gsl_vector_get (eval, index))
  458. index = 2;
  459. if (gsl_vector_get (eval, 3) > gsl_vector_get (eval, index))
  460. index = 3;
  461. //on ne garde que le vecteur prope associé à la valeur propre la plus élevée
  462. gsl_vector_view evec_i = gsl_matrix_column (evec, index);
  463. gsl_vector_free (eval);
  464. eval = &evec_i.vector;
  465. //rotation exprimé sous forme de quaternion
  466. q0 = gsl_vector_get (eval, 0);
  467. q1 = gsl_vector_get (eval, 1);
  468. q2 = gsl_vector_get (eval, 2);
  469. q3 = gsl_vector_get (eval, 3);
  470. rotation = gsl_matrix_alloc (3, 3);
  471. a2ri_erreur_critique_si (rotation == NULL,
  472. "erreur allocation memoire pour rotation\nIFcompute_rotation");
  473. //transformation du quaternion en matrice 3x3
  474. gsl_matrix_set (rotation, 0, 0, q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3);
  475. gsl_matrix_set (rotation, 0, 1, 2 * (q1 * q2 - q0 * q3));
  476. gsl_matrix_set (rotation, 0, 2, 2 * (q1 * q3 + q0 * q2));
  477. gsl_matrix_set (rotation, 1, 0, 2 * (q1 * q2 + q0 * q3));
  478. gsl_matrix_set (rotation, 1, 1, q0 * q0 + q2 * q2 - q1 * q1 - q3 * q3);
  479. gsl_matrix_set (rotation, 1, 2, 2 * (q2 * q3 - q0 * q1));
  480. gsl_matrix_set (rotation, 2, 0, 2 * (q1 * q3 - q0 * q2));
  481. gsl_matrix_set (rotation, 2, 1, 2 * (q2 * q3 + q0 * q1));
  482. gsl_matrix_set (rotation, 2, 2, q0 * q0 + q3 * q3 - q1 * q1 - q2 * q2);
  483. gsl_matrix_free (Exp);
  484. gsl_matrix_free (A);
  485. gsl_matrix_free (Exptrans);
  486. gsl_matrix_free (delta);
  487. gsl_matrix_free (QExp);
  488. gsl_matrix_free (identity3);
  489. gsl_matrix_free (trExpidentity3);
  490. gsl_matrix_free (basdroite);
  491. gsl_matrix_free (evec);
  492. return rotation;
  493. }
  494. gsl_matrix *
  495. IFcompute_translation (
  496. point3d * data_p,
  497. point3d * data_x,
  498. int nbpoint,
  499. gsl_matrix * rotation)
  500. {
  501. //voir article de Besl p243
  502. gsl_matrix *up,
  503. *ux,
  504. *mul,
  505. *trans;
  506. point3d *centerP,
  507. *centerX;
  508. double d[3];
  509. centerP = center_of_mass (data_p, nbpoint);
  510. centerX = center_of_mass (data_x, nbpoint);
  511. d[0] = centerP->x;
  512. d[1] = centerP->y;
  513. d[2] = centerP->z;
  514. up = matrix_init (d, 1, 3);
  515. d[0] = centerX->x;
  516. d[1] = centerX->y;
  517. d[2] = centerX->z;
  518. ux = matrix_init (d, 1, 3);
  519. mul = matrix_mul (up, rotation);
  520. trans = matrix_sub (ux, mul);
  521. gsl_matrix_free (up);
  522. gsl_matrix_free (ux);
  523. gsl_matrix_free (mul);
  524. free (centerP);
  525. free (centerX);
  526. return trans;
  527. }
  528. void
  529. IFapply_rotation_nv (
  530. vf_model *P,
  531. gsl_matrix * rotation)
  532. {
  533. gsl_matrix *pos1,
  534. *pos2;
  535. double data[3];
  536. for (int i = 0; i < P->nbvertex; i++)
  537. {
  538. data[0] = P->ve[i].x;
  539. data[1] = P->ve[i].y;
  540. data[2] = P->ve[i].z;
  541. pos1 = matrix_init (data, 1, 3);
  542. pos2 = matrix_mul (pos1, rotation);
  543. P->ve[i].x = gsl_matrix_get (pos2, 0, 0);
  544. P->ve[i].y = gsl_matrix_get (pos2, 0, 1);
  545. P->ve[i].z = gsl_matrix_get (pos2, 0, 2);
  546. gsl_matrix_free (pos1);
  547. gsl_matrix_free (pos2);
  548. }
  549. }
  550. void
  551. IFapply_translation_nv (
  552. vf_model *P,
  553. gsl_matrix * translation)
  554. {
  555. gsl_matrix *pos1,
  556. *pos2;
  557. double data[3];
  558. for (int i = 0; i < P->nbvertex; i++)
  559. {
  560. data[0] = P->ve[i].x;
  561. data[1] = P->ve[i].y;
  562. data[2] = P->ve[i].z;
  563. pos1 = matrix_init (data, 1, 3);
  564. pos2 = matrix_add (pos1, translation);
  565. P->ve[i].x = gsl_matrix_get (pos2, 0, 0);
  566. P->ve[i].y = gsl_matrix_get (pos2, 0, 1);
  567. P->ve[i].z = gsl_matrix_get (pos2, 0, 2);
  568. gsl_matrix_free (pos1);
  569. gsl_matrix_free (pos2);
  570. }
  571. }
  572. void
  573. IFapply_transformation_nv (
  574. vf_model * P,
  575. gsl_matrix * rotation,
  576. gsl_matrix * translation)
  577. {
  578. //application de la rotation puis translation et calcule de la nouvelle erreur
  579. IFapply_rotation_nv (P, rotation);
  580. IFapply_translation_nv (P, translation);
  581. P->xmin=P->ve[0].x;
  582. P->xmax=P->ve[0].x;
  583. P->ymin=P->ve[0].y;
  584. P->ymax=P->ve[0].y;
  585. P->zmin=P->ve[0].z;
  586. P->zmax=P->ve[0].z;
  587. for(int i=1;i<P->nbvertex;i++)
  588. {
  589. if (P->ve[i].x < P->xmin)
  590. P->xmin = P->ve[i].x;
  591. if (P->ve[i].x > P->xmax)
  592. P->xmax = P->ve[i].x;
  593. if (P->ve[i].y < P->ymin)
  594. P->ymin = P->ve[i].y;
  595. if (P->ve[i].y > P->ymax)
  596. P->ymax = P->ve[i].y;
  597. if (P->ve[i].z < P->zmin)
  598. P->zmin = P->ve[i].z;
  599. if (P->ve[i].z > P->zmax)
  600. P->zmax = P->ve[i].z;
  601. }
  602. }
  603. void
  604. IFapply_transformation_list_nv (
  605. vf_model ** P,
  606. int sizeP,
  607. gsl_matrix * rotation,
  608. gsl_matrix * translation)
  609. {
  610. for(int i=0;i<sizeP;i++)
  611. IFapply_transformation_nv(P[i],rotation,translation);
  612. }
  613. /********** MAIN FUNCTIONS **********/
  614. /**
  615. Recalage de deux modeles
  616. @param P modele à recaler
  617. @param X premier modele servant de base
  618. @param dkarret critère d'arret.
  619. @return aucun
  620. **/
  621. void
  622. a2ri_vf_icp (
  623. vf_model * P,
  624. const vf_model * const X,
  625. double dkarret)
  626. {
  627. //voir Besl p243 pour l'alogrithme général et
  628. //voir chetverikov pour le rejet
  629. gsl_matrix *rotation,
  630. *translation;
  631. point3d *data_p = NULL,
  632. *data_x = NULL,
  633. *data_pk = NULL;
  634. double erreur,
  635. erreurprec,
  636. delta=0;
  637. int nbpoint_p,
  638. nbpoint_pk,
  639. nbpoint_x,
  640. k = 0;
  641. double dk = 2.0,
  642. dk_1 = 1.0;
  643. delta = delta+2;
  644. point3d p1,
  645. p2;
  646. point3d_init (&p1, P->xmin, P->ymin, P->zmin);
  647. point3d_init (&p2, P->xmax, P->ymax, P->zmax);
  648. //critère d'arret : dk supérieur à notre critère d'arret,
  649. //nombre d'itération atteignant un certain seuil,
  650. //soustraction de deux dk successifs trop faible
  651. while ((dk_1 > dk && dk > dkarret && k < 200
  652. && ((fabs (dk - dk_1)) > (dkarret / 1000.0))) || k < 2)
  653. {
  654. erreurprec = erreur;
  655. dk_1 = dk;
  656. data_pk=a2ri_vf_to_list_point3d(P);
  657. nbpoint_pk = P->nbvertex;
  658. data_x=a2ri_vf_to_list_point3d(X);
  659. nbpoint_x = X->nbvertex;
  660. data_p=a2ri_vf_to_list_point3d(P);
  661. nbpoint_p = P->nbvertex;
  662. //Besl : étape a) -> mise en correspondance
  663. IFmise_en_correspondance (data_pk, &data_x, X, nbpoint_pk, &nbpoint_x);
  664. //chetverikov : on ne garde qu'un certain pourcentage de couple
  665. nbpoint_pk = nbpoint_p;
  666. nbpoint_x = nbpoint_p;
  667. //Besl : étape b) -> calcul de la transformation rigide
  668. rotation = IFcompute_rotation (data_pk, data_x, nbpoint_p);
  669. translation =
  670. IFcompute_translation (data_pk, data_x, nbpoint_p, rotation);
  671. erreur=IFcompute_error_nv(data_pk, data_x, nbpoint_p, rotation, translation);
  672. free (data_x);
  673. data_x = NULL;
  674. free (data_pk);
  675. data_pk = NULL;
  676. free (data_p);
  677. data_p = NULL;
  678. data_p=a2ri_vf_to_list_point3d(P);
  679. nbpoint_p = P->nbvertex;
  680. nbpoint_pk = nbpoint_p;
  681. //Besl : étape c) -> application de la transformation rigide
  682. IFapply_transformation_nv (P, rotation, translation);
  683. gsl_matrix_free (rotation);
  684. gsl_matrix_free (translation);
  685. k++;
  686. if (k > 1)
  687. {
  688. //Besl : étape d) -> fin de l'itération, calcul de l'erreur et réitération si nécessaire (voir le WHILE)
  689. delta = erreurprec / erreur;
  690. dk = (erreur * 100) / (point3d_length (&p1, &p2));
  691. }
  692. else
  693. {
  694. dk = (erreur * 100) / (point3d_length (&p1, &p2));
  695. dk_1 = dk + 1;
  696. }
  697. }
  698. if (data_p != NULL)
  699. free (data_p);
  700. if (data_x != NULL)
  701. free (data_x);
  702. if (data_pk != NULL)
  703. free (data_pk);
  704. }
  705. /**
  706. Recalage de deux modeles
  707. @param P modele à recaler
  708. @param X premier modele servant de base
  709. @param recouvrement estimation du taux de recouvrement
  710. @param dkarret critère d'arret.
  711. @return aucun
  712. **/
  713. void
  714. a2ri_vf_trimmed_icp (
  715. vf_model * P,
  716. const vf_model * const X,
  717. double recouvrement,
  718. double dkarret)
  719. {
  720. //voir Besl p243 pour l'alogrithme général et
  721. //voir chetverikov pour le rejet
  722. gsl_matrix *rotation,
  723. *translation;
  724. point3d *data_p = NULL,
  725. *data_x = NULL,
  726. *data_pk = NULL;
  727. double erreur,
  728. erreurprec,
  729. delta=0;
  730. int nbpoint_p,
  731. nbpoint_pk,
  732. nbpoint_x,
  733. k = 0;
  734. double dk = 2.0,
  735. dk_1 = 1.0;
  736. delta = delta+2;
  737. point3d p1,
  738. p2;
  739. point3d_init (&p1, P->xmin, P->ymin, P->zmin);
  740. point3d_init (&p2, P->xmax, P->ymax, P->zmax);
  741. //critère d'arret : dk supérieur à notre critère d'arret,
  742. //nombre d'itération atteignant un certain seuil,
  743. //soustraction de deux dk successifs trop faible
  744. while ((dk_1 > dk && dk > dkarret && k < 200
  745. && ((fabs (dk - dk_1)) > (dkarret / 1000.0))) || k < 2)
  746. {
  747. erreurprec = erreur;
  748. dk_1 = dk;
  749. data_pk=a2ri_vf_to_list_point3d(P);
  750. nbpoint_pk = P->nbvertex;
  751. data_x=a2ri_vf_to_list_point3d(X);
  752. nbpoint_x = X->nbvertex;
  753. data_p=a2ri_vf_to_list_point3d(P);
  754. nbpoint_p = P->nbvertex;
  755. //Besl : étape a) -> mise en correspondance
  756. IFmise_en_correspondance (data_pk, &data_x, X, nbpoint_pk, &nbpoint_x);
  757. //chetverikov : on ne garde qu'un certain pourcentage de couple
  758. IFrejet (&data_pk, &data_x, &data_p, &nbpoint_p, recouvrement);
  759. nbpoint_pk = nbpoint_p;
  760. nbpoint_x = nbpoint_p;
  761. //Besl : étape b) -> calcul de la transformation rigide
  762. rotation = IFcompute_rotation (data_pk, data_x, nbpoint_p);
  763. translation =
  764. IFcompute_translation (data_pk, data_x, nbpoint_p, rotation);
  765. erreur=IFcompute_error_nv(data_pk, data_x, nbpoint_p, rotation, translation);
  766. free (data_x);
  767. data_x = NULL;
  768. free (data_pk);
  769. data_pk = NULL;
  770. free (data_p);
  771. data_p = NULL;
  772. data_p=a2ri_vf_to_list_point3d(P);
  773. nbpoint_p = P->nbvertex;
  774. nbpoint_pk = nbpoint_p;
  775. //Besl : étape c) -> application de la transformation rigide
  776. IFapply_transformation_nv (P, rotation, translation);
  777. gsl_matrix_free (rotation);
  778. gsl_matrix_free (translation);
  779. k++;
  780. if (k > 1)
  781. {
  782. //Besl : étape d) -> fin de l'itération, calcul de l'erreur et réitération si nécessaire (voir le WHILE)
  783. delta = erreurprec / erreur;
  784. dk =
  785. ((erreur * 100) / (P->nbvertex * recouvrement)) /
  786. (point3d_length (&p1, &p2));
  787. }
  788. else
  789. {
  790. dk =
  791. ((erreur * 100) / (P->nbvertex * recouvrement)) /
  792. (point3d_length (&p1, &p2));
  793. dk_1 = dk + 1;
  794. }
  795. }
  796. if (data_p != NULL)
  797. free (data_p);
  798. if (data_x != NULL)
  799. free (data_x);
  800. if (data_pk != NULL)
  801. free (data_pk);
  802. }
  803. /**
  804. Recalage automatique de deux modeles
  805. @param P modele à recaler
  806. @param X premier modele servant de base
  807. @param dkarret critère d'arret.
  808. @param sensibility sensibilité du taux de recouvrement
  809. @return aucun
  810. **/
  811. //REMARQUE : le maillage devrait etre qualifié const mais impossible a cause de l'utilisation de la focntion a2ri_vf_bounding_ball_minimale_compute_overlap qui utilise des threads et ne permet donc pas la qualifidation de const du maillage.
  812. void
  813. a2ri_vf_automated_trimmed_icp (
  814. vf_model * P,
  815. vf_model * X,
  816. double dkarret,
  817. double sensibility)
  818. {
  819. //voir Besl p243 pour l'alogrithme général et
  820. //voir chetverikov pour le rejet
  821. gsl_matrix *rotation,
  822. *translation;
  823. point3d *data_p = NULL,
  824. *data_x = NULL,
  825. *data_pk = NULL;
  826. double erreur,
  827. erreurprec,
  828. delta=0;
  829. int nbpoint_p,
  830. nbpoint_pk,
  831. nbpoint_x,
  832. k = 0;
  833. double dk = 2.0,
  834. dk_1 = 1.0,
  835. recouvrement = 0;
  836. delta = delta+2;
  837. point3d p1,
  838. p2;
  839. point3d_init (&p1, P->xmin, P->ymin, P->zmin);
  840. point3d_init (&p2, P->xmax, P->ymax, P->zmax);
  841. //critère d'arret : dk supérieur à notre critère d'arret,
  842. //nombre d'itération atteignant un certain seuil,
  843. //soustraction de deux dk successifs trop faible
  844. while (((dk_1 > dk || (k - 1) % 10 == 0) && dk > dkarret
  845. && ((fabs (dk - dk_1)) > (dkarret / 1000.0))) || k < 2)
  846. {
  847. if (k % 10 == 0)
  848. {
  849. recouvrement =
  850. a2ri_vf_bounding_ball_minimale_compute_overlap (X, P,
  851. sensibility);
  852. }
  853. erreurprec = erreur;
  854. dk_1 = dk;
  855. data_pk=a2ri_vf_to_list_point3d(P);
  856. nbpoint_pk = P->nbvertex;
  857. data_x=a2ri_vf_to_list_point3d(X);
  858. nbpoint_x = X->nbvertex;
  859. data_p=a2ri_vf_to_list_point3d(P);
  860. nbpoint_p = P->nbvertex;
  861. //Besl : étape a) -> mise en correspondance
  862. IFmise_en_correspondance (data_pk, &data_x, X, nbpoint_pk, &nbpoint_x);
  863. //chetverikov : on ne garde qu'un certain pourcentage de couple
  864. IFrejet (&data_pk, &data_x, &data_p, &nbpoint_p, recouvrement);
  865. nbpoint_pk = nbpoint_p;
  866. nbpoint_x = nbpoint_p;
  867. //Besl : étape b) -> calcul de la transformation rigide
  868. rotation = IFcompute_rotation (data_pk, data_x, nbpoint_p);
  869. translation =
  870. IFcompute_translation (data_pk, data_x, nbpoint_p, rotation);
  871. erreur=IFcompute_error_nv(data_pk, data_x, nbpoint_p, rotation, translation);
  872. free (data_pk);
  873. data_pk = NULL;
  874. free (data_x);
  875. data_x = NULL;
  876. free (data_p);
  877. data_p = NULL;
  878. data_p=a2ri_vf_to_list_point3d(P);
  879. nbpoint_p = P->nbvertex;
  880. nbpoint_pk = nbpoint_p;
  881. //Besl : étape c) -> application de la transformation rigide
  882. IFapply_transformation_nv (P, rotation, translation);
  883. gsl_matrix_free (rotation);
  884. gsl_matrix_free (translation);
  885. k++;
  886. if (k > 1)
  887. {
  888. //Besl : étape d) -> fin de l'itération, calcul de l'erreur et réitération si nécessaire (voir le WHILE)
  889. delta = erreurprec / erreur;
  890. dk =
  891. ((erreur * 100) / (P->nbvertex * recouvrement)) /
  892. (point3d_length (&p1, &p2));
  893. }
  894. else
  895. {
  896. dk =
  897. ((erreur * 100) / (P->nbvertex * recouvrement)) /
  898. (point3d_length (&p1, &p2));
  899. dk_1 = dk + 1;
  900. }
  901. }
  902. if (data_p != NULL)
  903. free (data_p);
  904. if (data_x != NULL)
  905. free (data_x);
  906. if (data_pk != NULL)
  907. free (data_pk);
  908. }
  909. /**
  910. Recalage automatique de deux modeles
  911. @param P modele à recaler
  912. @param X premier modele servant de base
  913. @param dkarret critère d'arret.
  914. @return aucun
  915. **/
  916. //REMARQUE : le maillage devrait etre qualifié const mais impossible a cause de l'utilisation de thread.
  917. void
  918. a2ri_vf_automated_trimmed_icp_pulli (
  919. vf_model * P,
  920. vf_model * X,
  921. double dkarret)
  922. {
  923. //voir Besl p243 pour l'alogrithme général et
  924. //voir chetverikov pour le rejet
  925. gsl_matrix *rotation,
  926. *translation;
  927. point3d *data_x = NULL,
  928. *data_p = NULL;
  929. double erreur,
  930. erreurprec,
  931. delta=0;
  932. int nbpoint,
  933. k = 0;
  934. double dk = 2.0,
  935. dk_1 = 1.0;
  936. delta = delta+2;
  937. point3d p1,
  938. p2;
  939. point3d_init (&p1, P->xmin, P->ymin, P->zmin);
  940. point3d_init (&p2, P->xmax, P->ymax, P->zmax);
  941. //critère d'arret : dk supérieur à notre critère d'arret,
  942. //nombre d'itération atteignant un certain seuil,
  943. //soustraction de deux dk successifs trop faible
  944. while (((dk_1 > dk || (k - 1) % 10 == 0) && dk > dkarret
  945. && ((fabs (dk - dk_1)) > (dkarret / 1000.0))) || k < 2)
  946. {
  947. erreurprec = erreur;
  948. dk_1 = dk;
  949. free(data_p);
  950. data_p=NULL;
  951. free(data_x);
  952. data_x=NULL;
  953. //Besl : étape a) -> mise en correspondance
  954. IFmise_en_correspondance_pulli (P,X,&data_p,&data_x,&nbpoint);
  955. //Besl : étape b) -> calcul de la transformation rigide
  956. rotation = IFcompute_rotation (data_p, data_x, nbpoint);
  957. translation =
  958. IFcompute_translation (data_p, data_x, nbpoint, rotation);
  959. erreur=IFcompute_error_nv(data_p, data_x, nbpoint, rotation, translation);
  960. //Besl : étape c) -> application de la transformation rigide
  961. IFapply_transformation_nv (P, rotation, translation);
  962. gsl_matrix_free (rotation);
  963. gsl_matrix_free (translation);
  964. k++;
  965. if (k > 1)
  966. {
  967. //Besl : étape d) -> fin de l'itération, calcul de l'erreur et réitération si nécessaire (voir le WHILE)
  968. delta = erreurprec / erreur;
  969. dk =
  970. ((erreur * 100) / (nbpoint)) /
  971. (point3d_length (&p1, &p2));
  972. }
  973. else
  974. {
  975. dk =
  976. ((erreur * 100) / (nbpoint)) /
  977. (point3d_length (&p1, &p2));
  978. dk_1 = dk + 1;
  979. }
  980. }
  981. if (data_x != NULL)
  982. free (data_x);
  983. if (data_p != NULL)
  984. free (data_p);
  985. }
  986. /**
  987. Recalage automatique de deux modeles
  988. @param P tableau de modeles à recaler
  989. @param X tableau de modeles servant de référence
  990. @param sizeP nombre de modele dans P
  991. @param sizeX nombre de modele dans X
  992. @param dkarret critère d'arret.
  993. @param sensibility sensibilité du taux de recouvrement
  994. @return aucun
  995. **/
  996. //REMARQUE : le maillage devrait etre qualifié const mais impossible a cause de l'utilisation de la focntion a2ri_vf_bounding_ball_minimale_compute_overlap qui utilise des threads et ne permet donc pas la qualifidation de const du maillage.
  997. void
  998. a2ri_vf_automated_trimmed_icp_multiple (
  999. vf_model ** P,
  1000. vf_model ** X,
  1001. int sizeP,
  1002. int sizeX,
  1003. double dkarret,
  1004. double sensibility)
  1005. {
  1006. //voir Besl p243 pour l'alogrithme général et
  1007. //voir chetverikov pour le rejet
  1008. gsl_matrix *rotation,
  1009. *translation;
  1010. point3d *data_p = NULL,
  1011. *data_x = NULL,
  1012. *data_pk = NULL;
  1013. double erreur,
  1014. erreurprec,
  1015. delta=0;
  1016. int nbpoint_p,
  1017. nbpoint_pk,
  1018. nbpoint_x,
  1019. k = 0;
  1020. double dk = 2.0,
  1021. dk_1 = 1.0,
  1022. recouvrement = 0;
  1023. vf_model *tempX = NULL,
  1024. *tempP = NULL;
  1025. tempX = a2ri_vf_concat (X, sizeX);
  1026. delta = delta+2;
  1027. point3d p1,
  1028. p2;
  1029. point3d_init (&p1, tempP->xmin, tempP->ymin, tempP->zmin);
  1030. point3d_init (&p2, tempP->xmax, tempP->ymax, tempP->zmax);
  1031. //critère d'arret : dk supérieur à notre critère d'arret,
  1032. //nombre d'itération atteignant un certain seuil,
  1033. //soustraction de deux dk successifs trop faible
  1034. while (((dk_1 > dk || (k - 1) % 10 == 0) && ((fabs (dk - dk_1)) > dkarret))
  1035. || k < 2)
  1036. {
  1037. if (k % 10 == 0)
  1038. recouvrement =
  1039. a2ri_vf_bounding_ball_minimale_compute_overlap (tempX, tempP,
  1040. sensibility);
  1041. erreurprec = erreur;
  1042. dk_1 = dk;
  1043. a2ri_vf_free(tempP);
  1044. tempP=NULL;
  1045. tempP = a2ri_vf_concat (P, sizeP);
  1046. data_pk=a2ri_vf_to_list_point3d(tempP);
  1047. nbpoint_pk = tempP->nbvertex;
  1048. data_x=a2ri_vf_to_list_point3d(tempX);
  1049. nbpoint_x = tempX->nbvertex;
  1050. data_p=a2ri_vf_to_list_point3d(tempP);
  1051. nbpoint_p = tempP->nbvertex;
  1052. //Besl : étape a) -> mise en correspondance
  1053. IFmise_en_correspondance (data_pk, &data_x, tempX, nbpoint_pk,
  1054. &nbpoint_x);
  1055. //chetverikov : on ne garde qu'un certain pourcentage de couple
  1056. IFrejet (&data_pk, &data_x, &data_p, &nbpoint_p, recouvrement);
  1057. nbpoint_pk = nbpoint_p;
  1058. nbpoint_x = nbpoint_p;
  1059. //Besl : étape b) -> calcul de la transformation rigide
  1060. rotation = IFcompute_rotation (data_pk, data_x, nbpoint_p);
  1061. translation =
  1062. IFcompute_translation (data_pk, data_x, nbpoint_p, rotation);
  1063. erreur=IFcompute_error_nv(data_pk, data_x, nbpoint_p, rotation, translation);
  1064. free (data_pk);
  1065. data_pk = NULL;
  1066. free (data_x);
  1067. data_x = NULL;
  1068. free (data_p);
  1069. data_p = NULL;
  1070. data_p=a2ri_vf_to_list_point3d(tempP);
  1071. nbpoint_p = tempP->nbvertex;
  1072. nbpoint_pk = nbpoint_p;
  1073. //Besl : étape c) -> application de la transformation rigide
  1074. IFapply_transformation_list_nv (P, sizeP, rotation, translation);
  1075. gsl_matrix_free (rotation);
  1076. gsl_matrix_free (translation);
  1077. k++;
  1078. if (k > 1)
  1079. {
  1080. //Besl : étape d) -> fin de l'itération, calcul de l'erreur et réitération si nécessaire (voir le WHILE)
  1081. delta = erreurprec / erreur;
  1082. dk =
  1083. ((erreur * 100) / (tempP->nbvertex * recouvrement)) /
  1084. (point3d_length (&p1, &p2));
  1085. }
  1086. else
  1087. {
  1088. dk =
  1089. ((erreur * 100) / (tempP->nbvertex * recouvrement)) /
  1090. (point3d_length (&p1, &p2));
  1091. dk_1 = dk + 1;
  1092. }
  1093. }
  1094. if (data_p != NULL)
  1095. free (data_p);
  1096. if (data_x != NULL)
  1097. free (data_x);
  1098. if (data_pk != NULL)
  1099. free (data_pk);
  1100. a2ri_vf_free (tempP);
  1101. a2ri_vf_free (tempX);
  1102. }