quality.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555
  1. /*************************************/
  2. /* Auteur : Rémi Synave */
  3. /* Date de création : 03/04/07 */
  4. /* Date de modification : 18/09/16 */
  5. /* Version : 0.4 */
  6. /*************************************/
  7. /***************************************************************************/
  8. /* This file is part of a2ri. */
  9. /* */
  10. /* a2ri is free software: you can redistribute it and/or modify it */
  11. /* under the terms of the GNU Lesser General Public License as published */
  12. /* by the Free Software Foundation, either version 3 of the License, or */
  13. /* (at your option) any later version. */
  14. /* */
  15. /* a2ri is distributed in the hope that it will be useful, */
  16. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  17. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  18. /* GNU Lesser General Public License for more details. */
  19. /* */
  20. /* You should have received a copy of the GNU Lesser General Public */
  21. /* License along with a2ri. */
  22. /* If not, see <http://www.gnu.org/licenses/>. */
  23. /***************************************************************************/
  24. #include "quality.h"
  25. /********** INTERMEDIATE TYPES AND FUNCTIONS **********/
  26. /* Les fonctions intermédiaires sont préfixées de IF */
  27. /* et les types intermédiaires de IT */
  28. #define NB_SAMPLE_HAUSDORFF 50
  29. #define NB_SAMPLE_EMN 50
  30. typedef struct
  31. {
  32. vf_model *m;
  33. double *list;
  34. int size;
  35. } ITcouple;
  36. //ajout de la longueur de l'arete value dans la liste contenu dans la variable user_data
  37. void
  38. IFlongueur_arete (
  39. int key,
  40. vf_edge * value,
  41. void * user_data)
  42. {
  43. ITcouple *c = user_data;
  44. list_double_add (&((*c).list), &((*c).size), value->att_double,
  45. WITH_REDUNDANCE);
  46. }
  47. /********** MAIN FUNCTIONS **********/
  48. /**
  49. Calcul de l'erreur mean ratio metric sur un modèle pour une face
  50. @param m le modèle
  51. @param numface numéro de la face à évaluer
  52. @return évaluation de la face
  53. */
  54. double
  55. a2ri_vf_mean_ratio_metric_for_a_face (
  56. const vf_model * const m,
  57. int numface)
  58. {
  59. int ve1 = m->fa[numface].ve1;
  60. int ve2 = m->fa[numface].ve2;
  61. int ve3 = m->fa[numface].ve3;
  62. point3d p[3];
  63. point2d pnvbase[3];
  64. vector3d AB,
  65. AC,
  66. U;
  67. double a,
  68. b,
  69. c,
  70. d;
  71. //initialisation des triangles
  72. point3d_init (p, m->ve[ve1].x, m->ve[ve1].y, m->ve[ve1].z);
  73. point3d_init (p + 1, m->ve[ve2].x, m->ve[ve2].y, m->ve[ve2].z);
  74. point3d_init (p + 2, m->ve[ve3].x, m->ve[ve3].y, m->ve[ve3].z);
  75. //recherche equation du plan
  76. equation_plan (p, 3, &a, &b, &c, &d);
  77. //changement de base
  78. //initialisation du premier vecteur de la nouvelle base
  79. vector3d_init (&AB, p[1].x - p[0].x, p[1].y - p[0].y, p[1].z - p[0].z);
  80. vector3d_init (&AC, p[2].x - p[0].x, p[2].y - p[0].y, p[2].z - p[0].z);
  81. //recherche du second vecteur de la nouvelle base
  82. find_second_base_vector (&AB, &AC, &U);
  83. //normalisation des vecteurs
  84. vector3d_normalize (&AB);
  85. vector3d_normalize (&U);
  86. //recuperation des nouvelles coordonnées du point dans la nouvelle base
  87. base_modification_3d_to_2d (&(p[0]), &(p[0]), &AB, &U, &pnvbase[0]);
  88. base_modification_3d_to_2d (&(p[1]), &(p[0]), &AB, &U, &pnvbase[1]);
  89. base_modification_3d_to_2d (&(p[2]), &(p[0]), &AB, &U, &pnvbase[2]);
  90. //application du calcul mean ratio metric
  91. //-> article : A comparison of two optimization methods for mesh quality improvement
  92. gsl_matrix *A = gsl_matrix_alloc (2, 2);
  93. a2ri_erreur_critique_si (A == NULL,
  94. "erreur allocation memoire pour A\na2ri_vf_mean_ratio_metric_for_a_face");
  95. gsl_matrix_set (A, 0, 0, pnvbase[1].x - pnvbase[0].x);
  96. gsl_matrix_set (A, 0, 1, pnvbase[2].x - pnvbase[0].x);
  97. gsl_matrix_set (A, 1, 0, pnvbase[1].y - pnvbase[0].y);
  98. gsl_matrix_set (A, 1, 1, pnvbase[2].y - pnvbase[0].y);
  99. gsl_matrix *Winv = gsl_matrix_alloc (2, 2);
  100. a2ri_erreur_critique_si (Winv == NULL,
  101. "erreur allocation memoire pour Winv\na2ri_vf_mean_ratio_metric_for_a_face");
  102. gsl_matrix_set (Winv, 0, 0, 1);
  103. gsl_matrix_set (Winv, 0, 1, -1.0 / sqrt (3.0));
  104. gsl_matrix_set (Winv, 1, 0, 0);
  105. gsl_matrix_set (Winv, 1, 1, 2.0 / sqrt (3.0));
  106. gsl_matrix *S = matrix_mul (A, Winv);
  107. double erreurface =
  108. ((2 * matrix_determinant (S)) /
  109. (matrix_frobenius_norm (S) * matrix_frobenius_norm (S)));
  110. if (erreurface < 0)
  111. erreurface *= -1;
  112. gsl_matrix_free (A);
  113. gsl_matrix_free (Winv);
  114. gsl_matrix_free (S);
  115. return erreurface;
  116. }
  117. /**
  118. Calcul de l'erreur mean ratio metric sur un modèle complet
  119. @param m le modèle
  120. @return évaluation du modèle
  121. */
  122. double
  123. a2ri_vf_mean_ratio_metric (
  124. const vf_model * const m)
  125. {
  126. double somme = 0.0;
  127. for (int i = 0; i < m->nbface; i++)
  128. somme += a2ri_vf_mean_ratio_metric_for_a_face (m, i);
  129. somme /= (m->nbface) * 1.0;
  130. return somme;
  131. }
  132. /**
  133. Calcule la liste des angles des triangles composant le modèle
  134. @param m le modèle
  135. @param list pointeur sur le tableau contenant la liste des angles
  136. @param size pointeur sur la taille du tableau
  137. @return aucun
  138. */
  139. void
  140. a2ri_vf_list_angle (
  141. const vf_model * const m,
  142. double ** list,
  143. int * size)
  144. {
  145. *size = 0;
  146. *list = NULL;
  147. int ve1,
  148. ve2,
  149. ve3;
  150. double dx,
  151. dy,
  152. dz,
  153. angledegre;
  154. vector3d v1,
  155. v2;
  156. for (int i = 0; i < m->nbface; i++)
  157. {
  158. ve1 = m->fa[i].ve1;
  159. ve2 = m->fa[i].ve2;
  160. ve3 = m->fa[i].ve3;
  161. //angle ve1-ve2 ve1-ve3
  162. dx = m->ve[ve2].x - m->ve[ve1].x;
  163. dy = m->ve[ve2].y - m->ve[ve1].y;
  164. dz = m->ve[ve2].z - m->ve[ve1].z;
  165. vector3d_init (&v1, dx, dy, dz);
  166. dx = m->ve[ve3].x - m->ve[ve1].x;
  167. dy = m->ve[ve3].y - m->ve[ve1].y;
  168. dz = m->ve[ve3].z - m->ve[ve1].z;
  169. vector3d_init (&v2, dx, dy, dz);
  170. angledegre = vector3d_angle_degre (&v1, &v2);
  171. list_double_add (list, size, angledegre, WITH_REDUNDANCE);
  172. //angle ve2-ve1 ve2-ve3
  173. dx = m->ve[ve1].x - m->ve[ve2].x;
  174. dy = m->ve[ve1].y - m->ve[ve2].y;
  175. dz = m->ve[ve1].z - m->ve[ve2].z;
  176. vector3d_init (&v1, dx, dy, dz);
  177. dx = m->ve[ve3].x - m->ve[ve2].x;
  178. dy = m->ve[ve3].y - m->ve[ve2].y;
  179. dz = m->ve[ve3].z - m->ve[ve2].z;
  180. vector3d_init (&v2, dx, dy, dz);
  181. angledegre = vector3d_angle_degre (&v1, &v2);
  182. list_double_add (list, size, angledegre, WITH_REDUNDANCE);
  183. //angle ve3-ve2 ve3-ve1
  184. dx = m->ve[ve2].x - m->ve[ve3].x;
  185. dy = m->ve[ve2].y - m->ve[ve3].y;
  186. dz = m->ve[ve2].z - m->ve[ve3].z;
  187. vector3d_init (&v1, dx, dy, dz);
  188. dx = m->ve[ve1].x - m->ve[ve3].x;
  189. dy = m->ve[ve1].y - m->ve[ve3].y;
  190. dz = m->ve[ve1].z - m->ve[ve3].z;
  191. vector3d_init (&v2, dx, dy, dz);
  192. angledegre = vector3d_angle_degre (&v1, &v2);
  193. list_double_add (list, size, angledegre, WITH_REDUNDANCE);
  194. }
  195. }
  196. /**
  197. Calcule la liste des aires des triangles composant le modèle
  198. @param m le modèle
  199. @param list pointeur sur le tableau contenant la liste des aires
  200. @param size pointeur sur la taille du tableau
  201. @return aucun
  202. */
  203. void
  204. a2ri_vf_list_area (
  205. const vf_model * const m,
  206. double ** list,
  207. int * size)
  208. {
  209. int ve1,
  210. ve2,
  211. ve3;
  212. point3d p1,
  213. p2,
  214. p3;
  215. *list = NULL;
  216. *size = 0;
  217. double aire;
  218. for (int i = 0; i < m->nbface; i++)
  219. {
  220. ve1 = m->fa[i].ve1;
  221. ve2 = m->fa[i].ve2;
  222. ve3 = m->fa[i].ve3;
  223. point3d_init (&p1, m->ve[ve1].x, m->ve[ve1].y, m->ve[ve1].z);
  224. point3d_init (&p2, m->ve[ve2].x, m->ve[ve2].y, m->ve[ve2].z);
  225. point3d_init (&p3, m->ve[ve3].x, m->ve[ve3].y, m->ve[ve3].z);
  226. aire = point3d_area (&p1, &p2, &p3);
  227. list_double_add (list, size, aire, WITH_REDUNDANCE);
  228. }
  229. }
  230. /**
  231. Calcule la liste des valences des sommets composant le modèle
  232. @param m le modèle
  233. @param list pointeur sur le tableau contenant la liste des valences
  234. @param size pointeur sur la taille du tableau
  235. @return aucun
  236. */
  237. void
  238. a2ri_vf_list_valence (
  239. const vf_model * const m,
  240. int ** list,
  241. int * size)
  242. {
  243. *list = NULL;
  244. *size = 0;
  245. for (int i = 0; i < m->nbvertex; i++)
  246. list_int_add (list, size, m->ve[i].nbincidentvertices, WITH_REDUNDANCE);
  247. }
  248. /**
  249. Calcule la liste des longueurs des aretes composant le modèle
  250. @param m le modèle
  251. @param list pointeur sur le tableau contenant la liste des longueurs des aretes
  252. @param size pointeur sur la taille du tableau
  253. @return aucun
  254. */
  255. //On ne peut pas garantir le const du vf_model ici
  256. void
  257. a2ri_vf_list_edge_length (
  258. vf_model * m,
  259. double ** list,
  260. int * size)
  261. {
  262. ITcouple c;
  263. c.m = m;
  264. c.list = NULL;
  265. c.size = 0;
  266. ptf_func_hashtable func[1];
  267. func[0] = a2ri_vf_update_length_edge;
  268. //construction de la table de hachage des aretes
  269. hashtable *table = a2ri_vf_construction_edge_table (m, func, 1);
  270. //pour toute les aretes, on ajoute leur longueur dans la liste
  271. hashtable_foreach (table, IFlongueur_arete, &c);
  272. *list = c.list;
  273. *size = c.size;
  274. hashtable_free (table);
  275. free (table);
  276. }
  277. /**
  278. Calcule la liste des longueurs des hauteurs des triangles composant le modèle
  279. @param m le modèle
  280. @param list pointeur sur le tableau contenant la liste des hauteurs
  281. @param size pointeur sur la taille du tableau
  282. @return aucun
  283. */
  284. //On ne peut pas garantir le const du vf_model ici
  285. void
  286. a2ri_vf_list_height_length (
  287. vf_model * m,
  288. double ** list,
  289. int * size)
  290. {
  291. *list = NULL;
  292. *size = 0;
  293. point3d p1,
  294. p2,
  295. p3;
  296. vector3d v1,
  297. v2,
  298. vp;
  299. for (int i = 0; i < m->nbface; i++)
  300. {
  301. //initialisation des trois points correpondant aux trois sommets de la face
  302. point3d_init (&p1, m->ve[m->fa[i].ve1].x, m->ve[m->fa[i].ve1].y,
  303. m->ve[m->fa[i].ve1].z);
  304. point3d_init (&p2, m->ve[m->fa[i].ve2].x, m->ve[m->fa[i].ve2].y,
  305. m->ve[m->fa[i].ve2].z);
  306. point3d_init (&p3, m->ve[m->fa[i].ve3].x, m->ve[m->fa[i].ve3].y,
  307. m->ve[m->fa[i].ve3].z);
  308. //ajout de la première hauteur du triangle
  309. vector3d_init (&v1, p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
  310. vector3d_init (&v2, p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
  311. vp = vector3d_vectorialproduct (&v1, &v2);
  312. list_double_add (list, size, vector3d_size (&vp) / vector3d_size (&v1),
  313. WITH_REDUNDANCE);
  314. //ajout de la seconde hauteur du triangle
  315. vector3d_init (&v1, p1.x - p3.x, p1.y - p3.y, p1.z - p3.z);
  316. vector3d_init (&v2, p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
  317. vp = vector3d_vectorialproduct (&v1, &v2);
  318. list_double_add (list, size, vector3d_size (&vp) / vector3d_size (&v1),
  319. WITH_REDUNDANCE);
  320. //ajout de la troisieme hauteur du triangle
  321. vector3d_init (&v1, p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
  322. vector3d_init (&v2, p1.x - p3.x, p1.y - p3.y, p1.z - p3.z);
  323. vp = vector3d_vectorialproduct (&v1, &v2);
  324. list_double_add (list, size, vector3d_size (&vp) / vector3d_size (&v1),
  325. WITH_REDUNDANCE);
  326. }
  327. }
  328. /**
  329. Compte le nombre d'angles du modèle par intervalle de 10 degres
  330. @param m le modèle
  331. @return un tableau de 18 entiers contenant le nombre d'angle compris entre 0-10, 10-20, ... , 170-180
  332. */
  333. int *
  334. a2ri_vf_angle_measure (
  335. const vf_model * const m)
  336. {
  337. //|0-10|10-20|20-30|...|160-170|170-180|
  338. int *angle = (int *) malloc (18 * sizeof (int));
  339. a2ri_erreur_critique_si (angle == NULL,
  340. "erreur allocation memoire pour angle\na2ri_vf_angle_measure");
  341. int ve1,
  342. ve2,
  343. ve3,
  344. tabindice;
  345. double dx,
  346. dy,
  347. dz,
  348. angledegre;
  349. vector3d v1,
  350. v2;
  351. for (int i = 0; i < 18; i++)
  352. angle[i] = 0;
  353. for (int i = 0; i < m->nbface; i++)
  354. {
  355. ve1 = m->fa[i].ve1;
  356. ve2 = m->fa[i].ve2;
  357. ve3 = m->fa[i].ve3;
  358. //angle ve1-ve2 ve1-ve3
  359. dx = m->ve[ve2].x - m->ve[ve1].x;
  360. dy = m->ve[ve2].y - m->ve[ve1].y;
  361. dz = m->ve[ve2].z - m->ve[ve1].z;
  362. vector3d_init (&v1, dx, dy, dz);
  363. dx = m->ve[ve3].x - m->ve[ve1].x;
  364. dy = m->ve[ve3].y - m->ve[ve1].y;
  365. dz = m->ve[ve3].z - m->ve[ve1].z;
  366. vector3d_init (&v2, dx, dy, dz);
  367. angledegre = vector3d_angle_degre (&v1, &v2);
  368. angledegre *= 10;
  369. tabindice = (int) angledegre;
  370. if (tabindice % 10 >= 5)
  371. tabindice += 5;
  372. tabindice /= 100;
  373. angle[tabindice] = angle[tabindice] + 1;
  374. //angle ve2-ve1 ve2-ve3
  375. dx = m->ve[ve1].x - m->ve[ve2].x;
  376. dy = m->ve[ve1].y - m->ve[ve2].y;
  377. dz = m->ve[ve1].z - m->ve[ve2].z;
  378. vector3d_init (&v1, dx, dy, dz);
  379. dx = m->ve[ve3].x - m->ve[ve2].x;
  380. dy = m->ve[ve3].y - m->ve[ve2].y;
  381. dz = m->ve[ve3].z - m->ve[ve2].z;
  382. vector3d_init (&v2, dx, dy, dz);
  383. angledegre = vector3d_angle_degre (&v1, &v2);
  384. angledegre *= 10;
  385. tabindice = (int) angledegre;
  386. if (tabindice % 10 >= 5)
  387. tabindice += 5;
  388. tabindice /= 100;
  389. angle[tabindice] = angle[tabindice] + 1;
  390. //angle ve3-ve2 ve3-ve1
  391. dx = m->ve[ve2].x - m->ve[ve3].x;
  392. dy = m->ve[ve2].y - m->ve[ve3].y;
  393. dz = m->ve[ve2].z - m->ve[ve3].z;
  394. vector3d_init (&v1, dx, dy, dz);
  395. dx = m->ve[ve1].x - m->ve[ve3].x;
  396. dy = m->ve[ve1].y - m->ve[ve3].y;
  397. dz = m->ve[ve1].z - m->ve[ve3].z;
  398. vector3d_init (&v2, dx, dy, dz);
  399. angledegre = vector3d_angle_degre (&v1, &v2);
  400. angledegre *= 10;
  401. tabindice = (int) angledegre;
  402. if (tabindice % 10 >= 5)
  403. tabindice += 5;
  404. tabindice /= 100;
  405. angle[tabindice] = angle[tabindice] + 1;
  406. }
  407. return angle;
  408. }
  409. /**
  410. Calcul de l'erreur de Hausdorff
  411. @param m1 premier modèle
  412. @param m2 second modèle
  413. @return erreur de Hausdorff
  414. */
  415. double
  416. a2ri_vf_hausdorff (
  417. const vf_model * const m1,
  418. const vf_model * const m2,
  419. int sampling)
  420. {
  421. point3d *liste = NULL;
  422. point3d *listesamplem1 = NULL;
  423. point3d *listesamplem2 = NULL;
  424. double max = 0.0;
  425. point3d p,
  426. A,
  427. B,
  428. C;
  429. //premier cas : pas d'echantillonnage
  430. if (sampling == NO_SAMPLING)
  431. {
  432. //transformation des sommets de m2 en lsite de points
  433. liste = (point3d *) malloc (m2->nbvertex * sizeof (point3d));
  434. a2ri_erreur_critique_si (liste == NULL,
  435. "erreur allocation memoire pour liste\na2ri_vf_hausdorff");
  436. for (int i = 0; i < m2->nbvertex; i++)
  437. {
  438. liste[i].x = m2->ve[i].x;
  439. liste[i].y = m2->ve[i].y;
  440. liste[i].z = m2->ve[i].z;
  441. }
  442. //on cherche la longueur maximale entre les sommets de m1 et les somemts de m2
  443. for (int i = 0; i < m1->nbvertex; i++)
  444. {
  445. point3d_init (&p, m1->ve[i].x, m1->ve[i].y, m1->ve[i].z);
  446. double temp = DPP (&p, liste, m2->nbvertex);
  447. if (max < temp)
  448. max = temp;
  449. }
  450. free (liste);
  451. liste = NULL;
  452. //transformation des sommets de m1 en lsite de points
  453. liste = (point3d *) malloc (m1->nbvertex * sizeof (point3d));
  454. a2ri_erreur_critique_si (liste == NULL,
  455. "erreur allocation memoire pour liste\na2ri_vf_hausdorff");
  456. for (int i = 0; i < m1->nbvertex; i++)
  457. {
  458. liste[i].x = m1->ve[i].x;
  459. liste[i].y = m1->ve[i].y;
  460. liste[i].z = m1->ve[i].z;
  461. }
  462. //on cherche la longueur maximale entre les sommets de m2 et les somemts de m1
  463. for (int i = 0; i < m2->nbvertex; i++)
  464. {
  465. point3d_init (&p, m2->ve[i].x, m2->ve[i].y, m2->ve[i].z);
  466. double temp = DPP (&p, liste, m1->nbvertex);
  467. if (max < temp)
  468. max = temp;
  469. }
  470. free (liste);
  471. }
  472. else
  473. {
  474. listesamplem1 =
  475. (point3d *) malloc ((m1->nbvertex + m1->nbface * NB_SAMPLE_HAUSDORFF)
  476. * sizeof (point3d));
  477. a2ri_erreur_critique_si (listesamplem1 == NULL,
  478. "erreur allocation memoire pour listesamplem1\na2ri_vf_hausdorff");
  479. listesamplem2 =
  480. (point3d *) malloc ((m2->nbvertex + m2->nbface * NB_SAMPLE_HAUSDORFF)
  481. * sizeof (point3d));
  482. a2ri_erreur_critique_si (listesamplem2 == NULL,
  483. "erreur allocation memoire pour listesamplem2\na2ri_vf_hausdorff");
  484. //echantillonage de m1 et m2
  485. for (int i = 0; i < m1->nbvertex; i++)
  486. {
  487. listesamplem1[i].x = m1->ve[i].x;
  488. listesamplem1[i].y = m1->ve[i].y;
  489. listesamplem1[i].z = m1->ve[i].z;
  490. }
  491. for (int i = 0; i < m2->nbvertex; i++)
  492. {
  493. listesamplem2[i].x = m2->ve[i].x;
  494. listesamplem2[i].y = m2->ve[i].y;
  495. listesamplem2[i].z = m2->ve[i].z;
  496. }
  497. for (int i = 0; i < m1->nbface; i++)
  498. {
  499. point3d_init (&A, m1->ve[m1->fa[i].ve1].x, m1->ve[m1->fa[i].ve1].y,
  500. m1->ve[m1->fa[i].ve1].z);
  501. point3d_init (&B, m1->ve[m1->fa[i].ve2].x, m1->ve[m1->fa[i].ve2].y,
  502. m1->ve[m1->fa[i].ve2].z);
  503. point3d_init (&C, m1->ve[m1->fa[i].ve3].x, m1->ve[m1->fa[i].ve3].y,
  504. m1->ve[m1->fa[i].ve3].z);
  505. sample_triangle (&A, &B, &C, NB_SAMPLE_HAUSDORFF, &liste);
  506. for (int j = 0; j < NB_SAMPLE_HAUSDORFF; j++)
  507. {
  508. listesamplem1[(i * NB_SAMPLE_HAUSDORFF) + m1->nbvertex + j].x =
  509. liste[i].x;
  510. listesamplem1[(i * NB_SAMPLE_HAUSDORFF) + m1->nbvertex + j].y =
  511. liste[i].y;
  512. listesamplem1[(i * NB_SAMPLE_HAUSDORFF) + m1->nbvertex + j].z =
  513. liste[i].z;
  514. }
  515. }
  516. for (int i = 0; i < m2->nbface; i++)
  517. {
  518. point3d_init (&A, m2->ve[m2->fa[i].ve1].x, m2->ve[m2->fa[i].ve1].y,
  519. m2->ve[m2->fa[i].ve1].z);
  520. point3d_init (&B, m2->ve[m2->fa[i].ve2].x, m2->ve[m2->fa[i].ve2].y,
  521. m2->ve[m2->fa[i].ve2].z);
  522. point3d_init (&C, m2->ve[m2->fa[i].ve3].x, m2->ve[m2->fa[i].ve3].y,
  523. m2->ve[m2->fa[i].ve3].z);
  524. sample_triangle (&A, &B, &C, NB_SAMPLE_HAUSDORFF, &liste);
  525. for (int j = 0; j < NB_SAMPLE_HAUSDORFF; j++)
  526. {
  527. listesamplem2[(i * NB_SAMPLE_HAUSDORFF) + m2->nbvertex + j].x =
  528. liste[i].x;
  529. listesamplem2[(i * NB_SAMPLE_HAUSDORFF) + m2->nbvertex + j].y =
  530. liste[i].y;
  531. listesamplem2[(i * NB_SAMPLE_HAUSDORFF) + m2->nbvertex + j].z =
  532. liste[i].z;
  533. }
  534. }
  535. //recherche de la longueur max entre m1 et m2
  536. for (int i = 0; i < m1->nbvertex + m1->nbface * NB_SAMPLE_HAUSDORFF;
  537. i++)
  538. {
  539. double temp =
  540. DPP (&(listesamplem1[i]), listesamplem2,
  541. m2->nbvertex + m2->nbface * NB_SAMPLE_HAUSDORFF);
  542. if (max < temp)
  543. max = temp;
  544. }
  545. //recherche de la distance max entre m2 et m1
  546. for (int i = 0; i < m2->nbvertex + m2->nbface * NB_SAMPLE_HAUSDORFF;
  547. i++)
  548. {
  549. double temp =
  550. DPP (&(listesamplem2[i]), listesamplem1,
  551. m1->nbvertex + m1->nbface * NB_SAMPLE_HAUSDORFF);
  552. if (max < temp)
  553. max = temp;
  554. }
  555. free (listesamplem1);
  556. free (listesamplem2);
  557. }
  558. return max;
  559. }
  560. /**
  561. Calcul de la distance entre un point et un ensemble de points en se basant sur la métrique Point-Point
  562. @param p le point
  563. @param points tableau de réel contenant les coordoonées des sommets du maillage
  564. @param size taille du tableau
  565. @return distance entre le point et le modèle
  566. */
  567. double
  568. DPP (
  569. const point3d * const p,
  570. const point3d *const points,
  571. int size)
  572. {
  573. double min = 0;
  574. //on cherche la distance minimale entre un point p et un ensemble de points
  575. for (int i = 0; i < size; i++)
  576. {
  577. double temp = point3d_length (p, &(points[i]));
  578. if (i == 0)
  579. min = temp;
  580. else if (temp < min)
  581. min = temp;
  582. }
  583. return min;
  584. }
  585. /**
  586. Calcul de l'erreur moyenne "Emean" entre deux modèles
  587. @param m1 le premier modèle
  588. @param m2 le second modèle
  589. @param sampling SAMPLING ou NO_SAMPLING <BR> indique s'il faut ou non échantillonner les faces.
  590. @return l'erreur "Emean"
  591. */
  592. double
  593. a2ri_vf_Emn_DPP (
  594. const vf_model * const m1,
  595. const vf_model * const m2,
  596. int sampling)
  597. {
  598. point3d *liste = NULL;
  599. double erreur = 0.0;
  600. point3d p;
  601. //premier cas : pas d'echantillonnage
  602. if (sampling == NO_SAMPLING)
  603. {
  604. //transformation de la liste de sommets de m2 en liste de points
  605. liste = (point3d *) malloc (m2->nbvertex * sizeof (point3d));
  606. a2ri_erreur_critique_si (liste == NULL,
  607. "erreur allocation memoire pour liste\na2ri_vf_Emn_DPP");
  608. for (int i = 0; i < m2->nbvertex; i++)
  609. {
  610. liste[i].x = m2->ve[i].x;
  611. liste[i].y = m2->ve[i].y;
  612. liste[i].z = m2->ve[i].z;
  613. }
  614. //somme DPP(m1,m2)*DPP(m1,m2)
  615. for (int i = 0; i < m1->nbvertex; i++)
  616. {
  617. point3d_init (&p, m1->ve[i].x, m1->ve[i].y, m1->ve[i].z);
  618. double temp = DPP (&p, liste, m2->nbvertex);
  619. erreur += temp * temp;
  620. }
  621. free (liste);
  622. liste = NULL;
  623. //transformation de la liste de sommets de m1 en liste de points
  624. liste = (point3d *) malloc (m1->nbvertex * sizeof (point3d));
  625. a2ri_erreur_critique_si (liste == NULL,
  626. "erreur allocation memoire pour liste\na2ri_vf_Emn_DPP");
  627. for (int i = 0; i < m1->nbvertex; i++)
  628. {
  629. liste[i].x = m1->ve[i].x;
  630. liste[i].y = m1->ve[i].y;
  631. liste[i].z = m1->ve[i].z;
  632. }
  633. //somme DPP(m2,m1)*DPP(m2,m1)
  634. for (int i = 0; i < m2->nbvertex; i++)
  635. {
  636. point3d_init (&p, m2->ve[i].x, m2->ve[i].y, m2->ve[i].z);
  637. double temp = DPP (&p, liste, m1->nbvertex);
  638. erreur += temp * temp;
  639. }
  640. free (liste);
  641. }
  642. else
  643. {
  644. /*TODO meme algo avec echantillonnage*/
  645. erreur = -1;
  646. }
  647. return erreur / ((m1->nbvertex + m2->nbvertex) * 1.0);
  648. }
  649. /**
  650. Evaluation de l'aspect ratio d'un triangle
  651. @param m le modèle
  652. @param numface numéro de la face à évaluer
  653. @return évaluation de l'aspect ratio
  654. */
  655. double
  656. a2ri_vf_triangle_aspect_ratio (
  657. const vf_model * const m,
  658. int numface)
  659. {
  660. double distmax = 0,
  661. hauteur;
  662. int index = 0;
  663. point3d p1,
  664. p2,
  665. p3;
  666. vector3d v1,
  667. v2,
  668. vp;
  669. point3d_init (&p1, m->ve[m->fa[numface].ve1].x, m->ve[m->fa[numface].ve1].y,
  670. m->ve[m->fa[numface].ve1].z);
  671. point3d_init (&p2, m->ve[m->fa[numface].ve2].x, m->ve[m->fa[numface].ve2].y,
  672. m->ve[m->fa[numface].ve2].z);
  673. point3d_init (&p3, m->ve[m->fa[numface].ve3].x, m->ve[m->fa[numface].ve3].y,
  674. m->ve[m->fa[numface].ve3].z);
  675. //on cherche le plus grand cote
  676. distmax = point3d_length (&p1, &p2);
  677. if (distmax < point3d_length (&p1, &p3))
  678. {
  679. index = 1;
  680. distmax = point3d_length (&p1, &p3);
  681. }
  682. if (distmax < point3d_length (&p2, &p3))
  683. {
  684. index = 2;
  685. distmax = point3d_length (&p2, &p3);
  686. }
  687. //on cherche la hauteur du coté le plus grand
  688. switch (index)
  689. {
  690. case 0:
  691. vector3d_init (&v1, p1.x - p2.x, p1.y - p2.y, p1.z - p2.z);
  692. vector3d_init (&v2, p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
  693. break;
  694. case 1:
  695. vector3d_init (&v1, p3.x - p1.x, p3.y - p1.y, p3.z - p1.z);
  696. vector3d_init (&v2, p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
  697. break;
  698. case 2:
  699. vector3d_init (&v1, p2.x - p3.x, p2.y - p3.y, p2.z - p3.z);
  700. vector3d_init (&v2, p1.x - p3.x, p1.y - p3.y, p1.z - p3.z);
  701. break;
  702. }
  703. vp = vector3d_vectorialproduct (&v1, &v2);
  704. hauteur = vector3d_size (&vp) / vector3d_size (&v1);
  705. return (vector3d_size (&v1) / hauteur);
  706. }
  707. /**
  708. Evaluation de la qualité d'un triangle avec la méthode de Rypl
  709. @param m le modèle
  710. @param numface numéro de la face à évaluer
  711. @return évaluation de l'aspect ratio
  712. */
  713. double
  714. a2ri_vf_triangle_rypl (
  715. const vf_model * const m,
  716. int numface)
  717. {
  718. double a,
  719. b,
  720. c,
  721. aire;
  722. point3d p1,
  723. p2,
  724. p3;
  725. point3d_init (&p1, m->ve[m->fa[numface].ve1].x, m->ve[m->fa[numface].ve1].y,
  726. m->ve[m->fa[numface].ve1].z);
  727. point3d_init (&p2, m->ve[m->fa[numface].ve2].x, m->ve[m->fa[numface].ve2].y,
  728. m->ve[m->fa[numface].ve2].z);
  729. point3d_init (&p3, m->ve[m->fa[numface].ve3].x, m->ve[m->fa[numface].ve3].y,
  730. m->ve[m->fa[numface].ve3].z);
  731. aire = point3d_area (&p1, &p2, &p3);
  732. a = point3d_length (&p2, &p3);
  733. a = a * a;
  734. b = point3d_length (&p1, &p3);
  735. b = b * b;
  736. c = point3d_length (&p1, &p2);
  737. c = c * c;
  738. return (4 * sqrt (3) * aire / (a + b + c));
  739. }
  740. /**
  741. Calcul de la liste d'aspect ratio d'un modèle
  742. @param m le modèle
  743. @param list pointeur sur un tableau contenant tous les aspect ratio des triangles composant le modèle
  744. @param siuze pointeur sur la taille du tableau
  745. @return aucun
  746. */
  747. void
  748. a2ri_vf_list_triangle_aspect_ratio (
  749. const vf_model * const m,
  750. double ** list,
  751. int * size)
  752. {
  753. *list = NULL;
  754. *size = 0;
  755. for (int i = 0; i < m->nbface; i++)
  756. list_double_add (list, size, a2ri_vf_triangle_aspect_ratio (m, i),
  757. WITH_REDUNDANCE);
  758. }
  759. /**
  760. Calcul de la variation de taille (d'aire) entre deux faces du modèle
  761. @param m le modèle
  762. @param face1 numéro de la première face servant de base
  763. @param face2 numéro de la seconde face
  764. @return variation de la taille : Aire_face1/Aire_face2
  765. */
  766. double
  767. a2ri_vf_face_size_variation (
  768. const vf_model * const m,
  769. int face1,
  770. int face2)
  771. {
  772. point3d A,
  773. B,
  774. C,
  775. D,
  776. E,
  777. F;
  778. point3d_init (&A, m->ve[m->fa[face1].ve1].x, m->ve[m->fa[face1].ve1].y,
  779. m->ve[m->fa[face1].ve1].z);
  780. point3d_init (&B, m->ve[m->fa[face1].ve2].x, m->ve[m->fa[face1].ve2].y,
  781. m->ve[m->fa[face1].ve2].z);
  782. point3d_init (&C, m->ve[m->fa[face1].ve3].x, m->ve[m->fa[face1].ve3].y,
  783. m->ve[m->fa[face1].ve3].z);
  784. point3d_init (&D, m->ve[m->fa[face2].ve1].x, m->ve[m->fa[face2].ve1].y,
  785. m->ve[m->fa[face2].ve1].z);
  786. point3d_init (&E, m->ve[m->fa[face2].ve2].x, m->ve[m->fa[face2].ve2].y,
  787. m->ve[m->fa[face2].ve2].z);
  788. point3d_init (&F, m->ve[m->fa[face2].ve3].x, m->ve[m->fa[face2].ve3].y,
  789. m->ve[m->fa[face2].ve3].z);
  790. return (point3d_area (&A, &B, &C) / point3d_area (&D, &E, &F));
  791. }
  792. /**
  793. Calcul de la liste des rayons des cercles inscrit aux faces du modèles
  794. @param m le modèle
  795. @param list pointeur sur le tableau contenant la liste des rayons des cercles inscrits
  796. @param size pointeur sur la taille du tableau
  797. @return aucun
  798. */
  799. void
  800. a2ri_vf_list_radius_incircle (
  801. const vf_model * const m,
  802. double ** list,
  803. int * size)
  804. {
  805. point3d A,
  806. B,
  807. C,
  808. center;
  809. for (int i = 0; i < m->nbface; i++)
  810. {
  811. point3d_init (&A, m->ve[m->fa[i].ve1].x, m->ve[m->fa[i].ve1].y,
  812. m->ve[m->fa[i].ve1].z);
  813. point3d_init (&B, m->ve[m->fa[i].ve2].x, m->ve[m->fa[i].ve2].y,
  814. m->ve[m->fa[i].ve2].z);
  815. point3d_init (&C, m->ve[m->fa[i].ve3].x, m->ve[m->fa[i].ve3].y,
  816. m->ve[m->fa[i].ve3].z);
  817. center = incircle_center (&A, &B, &C);
  818. list_double_add (list, size,
  819. distance_point_straight_line (&center, &A, &B),
  820. WITH_REDUNDANCE);
  821. }
  822. }
  823. /**
  824. Calcul de la courbure de gauss pour un sommet
  825. @param m le modele
  826. @param ve numéro du sommet
  827. @return le courbure de gauss en ce sommet
  828. */
  829. double
  830. a2ri_vf_gauss_curvature (
  831. const vf_model * const m,
  832. int ve)
  833. {
  834. //TODO vérifier le bon fonctionnement de la fonction
  835. vector3d v1,
  836. v2;
  837. int *star = NULL,
  838. size = 0,
  839. ve1,
  840. ve2,
  841. ve3;
  842. double sommeangle = 0;
  843. a2ri_vf_faces_next_vertex (m, ve, &star, &size);
  844. for (int i = 0; i < size; i++)
  845. {
  846. ve1 = m->fa[star[i]].ve1;
  847. ve2 = m->fa[star[i]].ve2;
  848. ve3 = m->fa[star[i]].ve3;
  849. if (ve == ve2)
  850. {
  851. ve2 = ve1;
  852. ve1 = ve;
  853. }
  854. if (ve == ve3)
  855. {
  856. ve3 = ve1;
  857. ve1 = ve;
  858. }
  859. vector3d_init (&v1, m->ve[ve2].x - m->ve[ve1].x,
  860. m->ve[ve2].y - m->ve[ve1].y,
  861. m->ve[ve2].z - m->ve[ve1].z);
  862. vector3d_init (&v2, m->ve[ve3].x - m->ve[ve1].x,
  863. m->ve[ve3].y - m->ve[ve1].y,
  864. m->ve[ve3].z - m->ve[ve1].z);
  865. sommeangle += vector3d_angle_radian (&v1, &v2);
  866. }
  867. free (star);
  868. return (2.0 * PI - sommeangle);
  869. }
  870. /**
  871. Calcul de la courbure de gauss pour une liste de sommet
  872. @param m le modele
  873. @param ve liste de sommets
  874. @param size taille de la liste
  875. @param list liste des courbures associés à chaque sommet
  876. @return aucun
  877. */
  878. void
  879. a2ri_vf_gauss_curvature_list_of_vertex (
  880. const vf_model * const m,
  881. const int * const ve,
  882. int size,
  883. double ** list)
  884. {
  885. //TODO vérifier le bon fonctionnement de la fonction
  886. int newsize = 0;
  887. *list = NULL;
  888. for (int i = 0; i < size; i++)
  889. list_double_add (list, &newsize, a2ri_vf_gauss_curvature (m, ve[i]),
  890. WITH_REDUNDANCE);
  891. }
  892. /**
  893. calcule de la mean curvature pour une arete
  894. @param m le modele
  895. @param ve1 premier sommet de l'arete
  896. @param ve2 second sommet de l'arete
  897. @return la mean curvature pour cette arete
  898. */
  899. vector3d
  900. a2ri_vf_mean_curvature (
  901. const vf_model * const m,
  902. int ve1,
  903. int ve2)
  904. {
  905. int *list1 = NULL,
  906. *list2 = NULL,
  907. *list3 = NULL;
  908. int size1 = 0,
  909. size2 = 0,
  910. size3 = 0;
  911. vector3d retour,
  912. e,
  913. mu1,
  914. mu2;
  915. a2ri_vf_faces_next_vertex (m, ve1, &list1, &size1);
  916. a2ri_vf_faces_next_vertex (m, ve2, &list2, &size2);
  917. list_int_intersection (list1, size1, list2, size2, &list3, &size3);
  918. if (size3 != 2)
  919. {
  920. vector3d_init (&retour, 0, 0, 0);
  921. return retour;
  922. }
  923. vector3d_init (&e, m->ve[ve1].x - m->ve[ve2].x, m->ve[ve1].y - m->ve[ve2].y,
  924. m->ve[ve1].z - m->ve[ve2].z);
  925. mu1 = a2ri_vf_normal_face (m, list3[0]);
  926. mu2 = a2ri_vf_normal_face (m, list3[1]);
  927. vector3d_normalize (&mu1);
  928. vector3d_normalize (&mu2);
  929. vector3d vp1=vector3d_vectorialproduct (&e, &mu1);
  930. vector3d vp2=vector3d_vectorialproduct (&e, &mu2);
  931. return (vector3d_sub(&vp1,&vp2));
  932. }
  933. /**
  934. Calcul de la mean curvature pour un chemin
  935. @param m le modele
  936. @param list chemin décrit par ses sommets
  937. @param size taille du tableau list
  938. @param list_vector liste des vector3d retourner pour chaque arete
  939. @param size_list_vector taille de la liste list_vector
  940. @return aucun
  941. */
  942. void
  943. a2ri_vf_mean_curvature_path (
  944. const vf_model * const m,
  945. const int * const list,
  946. int size,
  947. vector3d ** list_vector,
  948. int * size_list_vector)
  949. {
  950. *size_list_vector = 0;
  951. *list_vector = NULL;
  952. for (int i = 0; i < size - 1; i++)
  953. {
  954. vector3d vtemp=a2ri_vf_mean_curvature (m, list[i], list[i + 1]);
  955. list_vector3d_add (list_vector, size_list_vector,
  956. &vtemp,
  957. WITH_REDUNDANCE);
  958. }
  959. }
  960. /**
  961. Calcul de la courbure de Levi-Civita
  962. @param m le modele
  963. @param numve numéro du sommet
  964. @return la courbure de Levi-Civita
  965. */
  966. double
  967. a2ri_vf_levi_civita (
  968. const vf_model * const m,
  969. int numve)
  970. {
  971. double sommeangle = 0;
  972. vector3d v1,
  973. v2;
  974. int index,
  975. fa1,
  976. fa2,
  977. *dejavu = NULL,
  978. size = 0;
  979. if (m->ve[numve].nbincidentvertices == 0)
  980. return 0;
  981. int prem = m->ve[numve].incidentvertices[0];
  982. index = prem++;
  983. list_int_add (&dejavu, &size, prem, WITH_REDUNDANCE);
  984. list_int_add (&dejavu, &size, numve, WITH_REDUNDANCE);
  985. hashtable *table = a2ri_vf_construction_edge_table (m, NULL, 0);
  986. vf_edge *temp = hashtable_look_for (table, numve, index);
  987. while (index != -1)
  988. {
  989. if (temp->nbsharedfaces != 2)
  990. return 0;
  991. fa1 = temp->sharedfaces[0];
  992. fa2 = temp->sharedfaces[1];
  993. v1 = a2ri_vf_normal_face (m, fa1);
  994. v2 = a2ri_vf_normal_face (m, fa2);
  995. sommeangle += vector3d_angle_radian (&v1, &v2);
  996. index = -1;
  997. if (list_int_contains (dejavu, size, m->fa[fa1].ve1) == -1)
  998. index = m->fa[fa1].ve1;
  999. if (list_int_contains (dejavu, size, m->fa[fa1].ve2) == -1)
  1000. index = m->fa[fa1].ve2;
  1001. if (list_int_contains (dejavu, size, m->fa[fa1].ve3) == -1)
  1002. index = m->fa[fa1].ve3;
  1003. if (list_int_contains (dejavu, size, m->fa[fa2].ve1) == -1)
  1004. index = m->fa[fa2].ve1;
  1005. if (list_int_contains (dejavu, size, m->fa[fa2].ve2) == -1)
  1006. index = m->fa[fa2].ve2;
  1007. if (list_int_contains (dejavu, size, m->fa[fa2].ve3) == -1)
  1008. index = m->fa[fa2].ve3;
  1009. list_int_add (&dejavu, &size, index, WITH_REDUNDANCE);
  1010. if (index != -1)
  1011. temp = hashtable_look_for (table, numve, index);
  1012. }
  1013. free (dejavu);
  1014. hashtable_free (table);
  1015. free (table);
  1016. return (2.0 * PI - sommeangle);
  1017. }
  1018. /**
  1019. Calcul de la courbure de Levi-Civita
  1020. @param m le modele
  1021. @param ve liste des numéros de sommets
  1022. @param size taille de la liste
  1023. @param list liste des courbures de levi-civita
  1024. @return aucun
  1025. */
  1026. void
  1027. a2ri_vf_levi_civita_list_of_vertex (
  1028. const vf_model * const m,
  1029. const int * const ve,
  1030. int size,
  1031. double ** list)
  1032. {
  1033. int newsize = 0;
  1034. *list = NULL;
  1035. for (int i = 0; i < size; i++)
  1036. list_double_add (list, &newsize, a2ri_vf_levi_civita (m, ve[i]),
  1037. WITH_REDUNDANCE);
  1038. }
  1039. /**
  1040. Calcul des courbures avec la méthode garimella
  1041. @param m le modele
  1042. @param numve numéro du sommet
  1043. @param K gaussian curvature
  1044. @param H mean curvature
  1045. @return aucun
  1046. **/
  1047. void
  1048. a2ri_vf_garimella (
  1049. const vf_model * const m,
  1050. int numve,
  1051. double * K,
  1052. double * H)
  1053. {
  1054. //TODO vérifier le bon fonctionnement de la fonction
  1055. vector3d X,
  1056. Y,
  1057. Z,
  1058. temp;
  1059. int *listface = NULL,
  1060. size_listface = 0;
  1061. int *listfacestar = NULL,
  1062. size_listfacestar = 0;
  1063. int *listvertex = NULL,
  1064. size_listvertex = 0;
  1065. point3d *sommet = NULL,
  1066. aajouter;
  1067. int size_sommet = 0;
  1068. double data2[3],
  1069. *data3,
  1070. *data4,
  1071. data3_temp[3],
  1072. data9_temp[9];
  1073. double a,
  1074. b,
  1075. c,
  1076. d,
  1077. e;
  1078. gsl_matrix *mat_identity,
  1079. *mat_normale,
  1080. *mat_normale_trans,
  1081. *mat_normale_carre,
  1082. *mat_i,
  1083. *mat_sous,
  1084. *mat_mul,
  1085. *mat_R;
  1086. mat_identity = gsl_matrix_calloc (3, 3);
  1087. a2ri_erreur_critique_si (mat_identity == NULL,
  1088. "erreur allocation memoire pour mat_identity\na2ri_vf_garimella");
  1089. gsl_matrix_set_identity (mat_identity);
  1090. //evaluer la normale au sommet numve qui est l'axe Z du nouveau repere
  1091. a2ri_vf_faces_next_vertex (m, numve, &listface, &size_listface);
  1092. vector3d_init (&Z, 0, 0, 0);
  1093. for (int i = 0; i < size_listface; i++)
  1094. {
  1095. temp = a2ri_vf_normal_face (m, listface[i]);
  1096. Z.dx += temp.dx;
  1097. Z.dy += temp.dy;
  1098. Z.dz += temp.dz;
  1099. }
  1100. vector3d_normalize (&Z);
  1101. //vector3d_reverse(&Z);
  1102. data3_temp[0] = Z.dx;
  1103. data3_temp[1] = Z.dy;
  1104. data3_temp[2] = Z.dz;
  1105. mat_normale = matrix_init (data3_temp, 3, 1);
  1106. mat_normale_trans = matrix_transpose (mat_normale);
  1107. mat_normale_carre = matrix_mul (mat_normale, mat_normale_trans);
  1108. if ((Z.dx == 1 || Z.dx == -1) && Z.dy == 0 && Z.dz == 0)
  1109. {
  1110. //cas particulier
  1111. data3_temp[0] = 0;
  1112. data3_temp[1] = 1;
  1113. data3_temp[2] = 0;
  1114. }
  1115. else
  1116. {
  1117. data3_temp[0] = 1;
  1118. data3_temp[1] = 0;
  1119. data3_temp[2] = 0;
  1120. }
  1121. mat_i = matrix_init (data3_temp, 3, 1);
  1122. mat_sous = matrix_sub (mat_identity, mat_normale_carre);
  1123. mat_mul = matrix_mul (mat_sous, mat_i);
  1124. X.dx = gsl_matrix_get (mat_mul, 0, 0);
  1125. X.dy = gsl_matrix_get (mat_mul, 1, 0);
  1126. X.dz = gsl_matrix_get (mat_mul, 2, 0);
  1127. Y = vector3d_vectorialproduct (&X, &Z);
  1128. vector3d_normalize (&X);
  1129. vector3d_normalize (&Y);
  1130. gsl_matrix_free (mat_mul);
  1131. gsl_matrix_free (mat_sous);
  1132. gsl_matrix_free (mat_normale_carre);
  1133. gsl_matrix_free (mat_normale);
  1134. gsl_matrix_free (mat_normale_trans);
  1135. gsl_matrix_free (mat_identity);
  1136. gsl_matrix_free (mat_i);
  1137. data9_temp[0] = X.dx;
  1138. data9_temp[1] = X.dy;
  1139. data9_temp[2] = X.dz;
  1140. data9_temp[3] = Y.dx;
  1141. data9_temp[4] = Y.dy;
  1142. data9_temp[5] = Y.dz;
  1143. data9_temp[6] = Z.dx;
  1144. data9_temp[7] = Z.dy;
  1145. data9_temp[8] = Z.dz;
  1146. mat_R = matrix_init (data9_temp, 3, 3);
  1147. //selectionner au moins 5 voisins
  1148. for (int i = 0; i < size_listface; i++)
  1149. {
  1150. if (m->fa[listface[i]].ve1 != numve)
  1151. list_int_add (&listvertex, &size_listvertex, m->fa[listface[i]].ve1,
  1152. WITHOUT_REDUNDANCE);
  1153. if (m->fa[listface[i]].ve2 != numve)
  1154. list_int_add (&listvertex, &size_listvertex, m->fa[listface[i]].ve2,
  1155. WITHOUT_REDUNDANCE);
  1156. if (m->fa[listface[i]].ve3 != numve)
  1157. list_int_add (&listvertex, &size_listvertex, m->fa[listface[i]].ve3,
  1158. WITHOUT_REDUNDANCE);
  1159. }
  1160. if (size_listvertex < 5)
  1161. {
  1162. free (listvertex);
  1163. listvertex = NULL;
  1164. size_listvertex = 0;
  1165. a2ri_vf_star (BYVERTEX, m, listface, size_listface, &listfacestar,
  1166. &size_listfacestar, 2);
  1167. for (int i = 0; i < size_listfacestar; i++)
  1168. {
  1169. if (m->fa[listfacestar[i]].ve1 != numve)
  1170. list_int_add (&listvertex, &size_listvertex,
  1171. m->fa[listfacestar[i]].ve1, WITHOUT_REDUNDANCE);
  1172. if (m->fa[listfacestar[i]].ve2 != numve)
  1173. list_int_add (&listvertex, &size_listvertex,
  1174. m->fa[listfacestar[i]].ve2, WITHOUT_REDUNDANCE);
  1175. if (m->fa[listfacestar[i]].ve3 != numve)
  1176. list_int_add (&listvertex, &size_listvertex,
  1177. m->fa[listfacestar[i]].ve3, WITHOUT_REDUNDANCE);
  1178. }
  1179. }
  1180. free (listface);
  1181. //changement de repère pour les voisins
  1182. //translation des sommets
  1183. for (int i = 0; i < size_listvertex; i++)
  1184. {
  1185. point3d_init (&aajouter,
  1186. m->ve[listvertex[i]].x - m->ve[numve].x,
  1187. m->ve[listvertex[i]].y - m->ve[numve].y,
  1188. m->ve[listvertex[i]].z - m->ve[numve].z);
  1189. list_point3d_add (&sommet, &size_sommet, &aajouter, WITH_REDUNDANCE);
  1190. }
  1191. free (listvertex);
  1192. //changement de repere avec la matrice R
  1193. for (int i = 0; i < size_sommet; i++)
  1194. {
  1195. data2[0] = sommet[i].x;
  1196. data2[1] = sommet[i].y;
  1197. data2[2] = sommet[i].z;
  1198. gsl_matrix *m = matrix_init (data2, 3, 1);
  1199. gsl_matrix *mul = matrix_mul (mat_R, m);
  1200. sommet[i].x = gsl_matrix_get (mul, 0, 0);
  1201. sommet[i].y = gsl_matrix_get (mul, 1, 0);
  1202. sommet[i].z = gsl_matrix_get (mul, 2, 0);
  1203. gsl_matrix_free (m);
  1204. gsl_matrix_free (mul);
  1205. }
  1206. //resolution avec la methodes des moindres carres
  1207. data3 = (double *) malloc (5 * size_sommet * sizeof (double));
  1208. a2ri_erreur_critique_si (data3 == NULL,
  1209. "erreur allocation memoire pour data3\na2ri_vf_garimella");
  1210. data4 = (double *) malloc (size_sommet * sizeof (double));
  1211. a2ri_erreur_critique_si (data4 == NULL,
  1212. "erreur allocation memoire pour data4\na2ri_vf_garimella");
  1213. for (int i = 0; i < size_sommet; i++)
  1214. {
  1215. data3[i * 5] = sommet[i].x * sommet[i].x;
  1216. data3[i * 5 + 1] = sommet[i].x * sommet[i].y;
  1217. data3[i * 5 + 2] = sommet[i].y * sommet[i].y;
  1218. data3[i * 5 + 3] = sommet[i].x;
  1219. data3[i * 5 + 4] = sommet[i].y;
  1220. data4[i] = sommet[i].z;
  1221. }
  1222. gsl_matrix *A = matrix_init (data3, size_sommet, 5);
  1223. gsl_matrix *B = matrix_init (data4, size_sommet, 1);
  1224. gsl_matrix *transA = matrix_transpose (A);
  1225. gsl_matrix *multransAA = matrix_mul (transA, A);
  1226. gsl_matrix *invmultransAA = matrix_inverse (multransAA);
  1227. gsl_matrix *pseudoinverse = matrix_mul (invmultransAA, transA);
  1228. gsl_matrix *x = matrix_mul (pseudoinverse, B);
  1229. a = gsl_matrix_get (x, 0, 0);
  1230. b = gsl_matrix_get (x, 1, 0);
  1231. c = gsl_matrix_get (x, 2, 0);
  1232. d = gsl_matrix_get (x, 3, 0);
  1233. e = gsl_matrix_get (x, 4, 0);
  1234. gsl_matrix_free (A);
  1235. gsl_matrix_free (B);
  1236. gsl_matrix_free (pseudoinverse);
  1237. gsl_matrix_free (x);
  1238. gsl_matrix_free (transA);
  1239. gsl_matrix_free (multransAA);
  1240. gsl_matrix_free (invmultransAA);
  1241. free (sommet);
  1242. //calcul des courbures
  1243. *K = (4 * a * c * -b * b) / ((1 + d * d + e * e) * (1 + d * d + e * e));
  1244. *H =
  1245. (a + c + a * e * e + c * d * d -
  1246. b * d * e) / (pow (1 + d * d + e * e, 1.5));
  1247. }
  1248. /**
  1249. Calcul de la précision, justesse d'un squelette par rapport à un modèle numérique
  1250. @param m le modèle
  1251. @param s le squelette
  1252. @return un nombre définissant la précision du squelette par rapport au modèle. Plus ce nombre sera élevé, moins le squelette sera ajusté au modèle.
  1253. **/
  1254. int a2ri_vf_model_skeleton_accuracy(
  1255. const vf_model * const m,
  1256. const skeleton * const s)
  1257. {
  1258. /*int non_visible=0;
  1259. for(int i=0;i<m->nbvertex;i++)
  1260. for(int j=0;j<s->nbvertex;j++)
  1261. {
  1262. int cpt=0;
  1263. point3d s1,s2,t1,t2,t3;
  1264. double t;
  1265. point3d_init(&s1,m->ve[i].x,m->ve[i].y,m->ve[i].z);
  1266. point3d_init(&s2,s->ve[j].x,s->ve[j].y,s->ve[j].z);
  1267. point3d_init(&t1,m->ve[m->fa[cpt].ve1].x,m->ve[m->fa[cpt].ve1].y,m->ve[m->fa[cpt].ve1].z);
  1268. point3d_init(&t2,m->ve[m->fa[cpt].ve2].x,m->ve[m->fa[cpt].ve2].y,m->ve[m->fa[cpt].ve2].z);
  1269. point3d_init(&t3,m->ve[m->fa[cpt].ve3].x,m->ve[m->fa[cpt].ve3].y,m->ve[m->fa[cpt].ve3].z);
  1270. //while(cpt<m->nbface && !intersection_segment_triangle(&s1,&s2,&t1,&t2,&t3,&t))
  1271. // {
  1272. // cpt++;
  1273. // if(cpt!=m->nbface)
  1274. // {
  1275. //point3d_init(&t1,m->ve[m->fa[cpt].ve1].x,m->ve[m->fa[cpt].ve1].y,m->ve[m->fa[cpt].ve1].z);
  1276. // point3d_init(&t2,m->ve[m->fa[cpt].ve2].x,m->ve[m->fa[cpt].ve2].y,m->ve[m->fa[cpt].ve2].z);
  1277. // point3d_init(&t3,m->ve[m->fa[cpt].ve3].x,m->ve[m->fa[cpt].ve3].y,m->ve[m->fa[cpt].ve3].z);
  1278. // }
  1279. // }
  1280. int fin=0;
  1281. while(cpt<m->nbface && !fin)
  1282. {
  1283. printf("-----------------\n");
  1284. printf("point du modele numerique : (%lf , %lf , %lf)\n",s1.x,s1.y,s1.z);
  1285. printf("point du squelette : (%lf , %lf , %lf)\n",s2.x,s2.y,s2.z);
  1286. printf("test face : %d - (%lf , %lf , %lf) (%lf , %lf , %lf) (%lf , %lf , %lf)\n",cpt,t1.x,t1.y,t1.z,t2.x,t2.y,t2.z,t3.x,t3.y,t3.z);
  1287. if(intersection_segment_triangle(&s1,&s2,&t1,&t2,&t3,&t))
  1288. printf("********************************************intersection en t = %lf - (%lf , %lf , %lf)\n",t,s1.x+t*(s2.x-s1.x),s1.y+t*(s2.y-s1.y),s1.z+t*(s2.z-s1.z));
  1289. else
  1290. printf("Pas d'intersection\n");
  1291. printf("-----------------\n");
  1292. if(!intersection_segment_triangle(&s1,&s2,&t1,&t2,&t3,&t))
  1293. fin=1;
  1294. cpt++;
  1295. if(cpt!=m->nbface)
  1296. {
  1297. point3d_init(&t1,m->ve[m->fa[cpt].ve1].x,m->ve[m->fa[cpt].ve1].y,m->ve[m->fa[cpt].ve1].z);
  1298. point3d_init(&t2,m->ve[m->fa[cpt].ve2].x,m->ve[m->fa[cpt].ve2].y,m->ve[m->fa[cpt].ve2].z);
  1299. point3d_init(&t3,m->ve[m->fa[cpt].ve3].x,m->ve[m->fa[cpt].ve3].y,m->ve[m->fa[cpt].ve3].z);
  1300. }
  1301. }
  1302. if(cpt==m->nbface)
  1303. non_visible++;
  1304. }
  1305. return non_visible;*/
  1306. int non_visible=0;
  1307. point3d s1,s2,t1,t2,t3;
  1308. double t;
  1309. for(int i=0;i<m->nbvertex;i++)
  1310. {
  1311. point3d_init(&s1,m->ve[i].x,m->ve[i].y,m->ve[i].z);
  1312. for(int j=0;j<s->nbvertex;j++)
  1313. {
  1314. point3d_init(&s2,s->ve[j].x,s->ve[j].y,s->ve[j].z);
  1315. int nb_intersection=0;
  1316. int k=0;
  1317. while(k<m->nbface && nb_intersection==0)
  1318. {
  1319. point3d_init(&t1,m->ve[m->fa[k].ve1].x,m->ve[m->fa[k].ve1].y,m->ve[m->fa[k].ve1].z);
  1320. point3d_init(&t2,m->ve[m->fa[k].ve2].x,m->ve[m->fa[k].ve2].y,m->ve[m->fa[k].ve2].z);
  1321. point3d_init(&t3,m->ve[m->fa[k].ve3].x,m->ve[m->fa[k].ve3].y,m->ve[m->fa[k].ve3].z);
  1322. if(intersection_segment_triangle(&s1,&s2,&t1,&t2,&t3,&t))
  1323. nb_intersection++;
  1324. k++;
  1325. }
  1326. if(nb_intersection>0)
  1327. non_visible++;
  1328. }
  1329. }
  1330. return non_visible;
  1331. }