boundingbox.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  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. /* 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 "boundingbox.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. /********** MAIN FUNCTIONS **********/
  29. /**
  30. Calcul des boites englobantes (parallélépipèdes) des faces de la liste
  31. @param m le modèle
  32. @param faces tableau contenant les numéros des faces pour lesquels on veut les boites englobantes
  33. @param nbfaces taille du tableau
  34. @param ptmin pointeur sur le tableau contenant les points (xmin,ymin,zmin) des boites englobantes
  35. @param ptmax pointeur sur le tableau contenant les points (xmax,ymax,zmax) des boites englobantes
  36. **/
  37. void
  38. a2ri_vf_axis_aligned_bounding_box (
  39. const vf_model * const m,
  40. const int * const faces,
  41. int nbfaces,
  42. point3d ** ptmin,
  43. point3d ** ptmax)
  44. {
  45. //allocation de l'espace pour les tableaux ptmin et ptmax
  46. (*ptmin) = (point3d *) malloc (nbfaces * sizeof (point3d));
  47. a2ri_erreur_critique_si (*ptmin == NULL,
  48. "erreur allocation memoire pour ptmin\na2ri_vf_axis_aligned_bounding_box");
  49. (*ptmax) = (point3d *) malloc (nbfaces * sizeof (point3d));
  50. a2ri_erreur_critique_si (*ptmax == NULL,
  51. "erreur allocation memoire pour ptmax\na2ri_vf_axis_aligned_bounding_box");
  52. for (int i = 0; i < nbfaces; i++)
  53. {
  54. //pour la face i : renseignement des coins ptmin et ptmax avec le sommet ve1
  55. (*ptmin)[faces[i]].x = m->ve[m->fa[faces[i]].ve1].x;
  56. (*ptmin)[faces[i]].y = m->ve[m->fa[faces[i]].ve1].y;
  57. (*ptmin)[faces[i]].z = m->ve[m->fa[faces[i]].ve1].z;
  58. (*ptmax)[faces[i]].x = m->ve[m->fa[faces[i]].ve1].x;
  59. (*ptmax)[faces[i]].y = m->ve[m->fa[faces[i]].ve1].y;
  60. (*ptmax)[faces[i]].z = m->ve[m->fa[faces[i]].ve1].z;
  61. //mise à jour si nécessaire avec ve2 et ve3
  62. if (m->ve[m->fa[faces[i]].ve2].x < (*ptmin)[faces[i]].x)
  63. (*ptmin)[faces[i]].x = m->ve[m->fa[faces[i]].ve2].x;
  64. if (m->ve[m->fa[faces[i]].ve2].y < (*ptmin)[faces[i]].y)
  65. (*ptmin)[faces[i]].y = m->ve[m->fa[faces[i]].ve2].y;
  66. if (m->ve[m->fa[faces[i]].ve2].z < (*ptmin)[faces[i]].z)
  67. (*ptmin)[faces[i]].z = m->ve[m->fa[faces[i]].ve2].z;
  68. if (m->ve[m->fa[faces[i]].ve2].x > (*ptmax)[faces[i]].x)
  69. (*ptmax)[faces[i]].x = m->ve[m->fa[faces[i]].ve2].x;
  70. if (m->ve[m->fa[faces[i]].ve2].y > (*ptmax)[faces[i]].y)
  71. (*ptmax)[faces[i]].y = m->ve[m->fa[faces[i]].ve2].y;
  72. if (m->ve[m->fa[faces[i]].ve2].z > (*ptmax)[faces[i]].z)
  73. (*ptmax)[faces[i]].z = m->ve[m->fa[faces[i]].ve2].z;
  74. if (m->ve[m->fa[faces[i]].ve3].x < (*ptmin)[faces[i]].x)
  75. (*ptmin)[faces[i]].x = m->ve[m->fa[faces[i]].ve3].x;
  76. if (m->ve[m->fa[faces[i]].ve3].y < (*ptmin)[faces[i]].y)
  77. (*ptmin)[faces[i]].y = m->ve[m->fa[faces[i]].ve3].y;
  78. if (m->ve[m->fa[faces[i]].ve3].z < (*ptmin)[faces[i]].z)
  79. (*ptmin)[faces[i]].z = m->ve[m->fa[faces[i]].ve3].z;
  80. if (m->ve[m->fa[faces[i]].ve3].x > (*ptmax)[faces[i]].x)
  81. (*ptmax)[faces[i]].x = m->ve[m->fa[faces[i]].ve3].x;
  82. if (m->ve[m->fa[faces[i]].ve3].y > (*ptmax)[faces[i]].y)
  83. (*ptmax)[faces[i]].y = m->ve[m->fa[faces[i]].ve3].y;
  84. if (m->ve[m->fa[faces[i]].ve3].z > (*ptmax)[faces[i]].z)
  85. (*ptmax)[faces[i]].z = m->ve[m->fa[faces[i]].ve3].z;
  86. }
  87. }
  88. /**
  89. Calcul des sphères englobantes des faces de la liste en utilisant les fastball de Ritter
  90. @param m le modèle
  91. @param faces tableau contenant les numéros des faces pour lesquels on veut les sphères englobantes
  92. @param nbfaces taille du tableau
  93. @param listcentre pointeur sur le tableau de point3d contenant les centres de sphères englobantes
  94. @param listradius pointeur sur le tableau contenant les rayons des sphères englobantes
  95. **/
  96. void
  97. a2ri_vf_bounding_ball_ritter (
  98. const vf_model * const m,
  99. const int * const faces,
  100. int nbfaces,
  101. point3d ** listcentre,
  102. double **listradius)
  103. {
  104. int nbelt = 0;
  105. //allocation de l'espae pour les centres des sphères
  106. *listcentre = (point3d *) malloc (nbfaces * sizeof (point3d));
  107. a2ri_erreur_critique_si (*listcentre == NULL,
  108. "erreur allocation memoire pour listcentre\na2ri_vf_bounding_ball_ritter");
  109. for (int i = 0; i < nbfaces; i++)
  110. {
  111. //pour la face faces[i]
  112. int ve1 = m->fa[faces[i]].ve1;
  113. int ve2 = m->fa[faces[i]].ve2;
  114. int ve3 = m->fa[faces[i]].ve3;
  115. //calcul de la boite englobgante
  116. double xmin = m->ve[ve1].x;
  117. double xmax = xmin;
  118. double ymin = m->ve[ve1].y;
  119. double ymax = ymin;
  120. double zmin = m->ve[ve1].z;
  121. double zmax = zmin;
  122. if (m->ve[ve2].x < xmin)
  123. xmin = m->ve[ve2].x;
  124. if (m->ve[ve2].x > xmax)
  125. xmax = m->ve[ve2].x;
  126. if (m->ve[ve3].x < xmin)
  127. xmin = m->ve[ve3].x;
  128. if (m->ve[ve3].x > xmax)
  129. xmax = m->ve[ve3].x;
  130. if (m->ve[ve2].y < ymin)
  131. ymin = m->ve[ve2].y;
  132. if (m->ve[ve2].y > ymax)
  133. ymax = m->ve[ve2].y;
  134. if (m->ve[ve3].y < ymin)
  135. ymin = m->ve[ve3].y;
  136. if (m->ve[ve3].y > ymax)
  137. ymax = m->ve[ve3].y;
  138. if (m->ve[ve2].z < zmin)
  139. zmin = m->ve[ve2].z;
  140. if (m->ve[ve2].z > zmax)
  141. zmax = m->ve[ve2].z;
  142. if (m->ve[ve3].z < zmin)
  143. zmin = m->ve[ve3].z;
  144. if (m->ve[ve3].z > zmax)
  145. zmax = m->ve[ve3].z;
  146. //calcul du centre de la boite englobante
  147. double centrex = (xmin + xmax) / 2.0;
  148. double centrey = (ymin + ymax) / 2.0;
  149. double centrez = (zmin + zmax) / 2.0;
  150. (*listcentre)[i].x = centrex;
  151. (*listcentre)[i].y = centrey;
  152. (*listcentre)[i].z = centrez;
  153. //calcul des trois rayons -> centre-ve1, centre-ve2, centre-ve3
  154. double radius1 =
  155. sqrt ((centrex - m->ve[ve1].x) * (centrex - m->ve[ve1].x) +
  156. (centrey - m->ve[ve1].y) * (centrey - m->ve[ve1].y) + (centrez -
  157. m->ve[ve1].
  158. z) *
  159. (centrez - m->ve[ve1].z));
  160. double radius2 =
  161. sqrt ((centrex - m->ve[ve2].x) * (centrex - m->ve[ve2].x) +
  162. (centrey - m->ve[ve2].y) * (centrey - m->ve[ve2].y) + (centrez -
  163. m->ve[ve2].
  164. z) *
  165. (centrez - m->ve[ve2].z));
  166. double radius3 =
  167. sqrt ((centrex - m->ve[ve3].x) * (centrex - m->ve[ve3].x) +
  168. (centrey - m->ve[ve3].y) * (centrey - m->ve[ve3].y) + (centrez -
  169. m->ve[ve3].
  170. z) *
  171. (centrez - m->ve[ve3].z));
  172. if (radius2 > radius1)
  173. radius1 = radius2;
  174. if (radius3 > radius1)
  175. radius1 = radius3;
  176. //ajout du rayon maximal à la liste des rayons
  177. list_double_add (listradius, &nbelt, radius1, WITH_REDUNDANCE);
  178. }
  179. }
  180. /**
  181. Calcul des sphères englobantes des faces de la liste
  182. @param m le modèle
  183. @param faces tableau contenant les numéros des faces pour lesquels on veut les sphères englobantes
  184. @param nbfaces taille du tableau
  185. @param listcentre pointeur sur le tableau de point3d contenant les centres de sphères englobantes
  186. @param listradius pointeur sur le tableau contenant les rayons des sphères englobantes
  187. **/
  188. void
  189. a2ri_vf_bounding_ball_minimale (
  190. const vf_model * const m,
  191. const int * const faces,
  192. int nbfaces,
  193. point3d ** listcentre,
  194. double **listradius)
  195. {
  196. double radius,
  197. x,
  198. y,
  199. z;
  200. int ve1,
  201. ve2,
  202. ve3,
  203. nbelt = 0;
  204. point3d p3d_1,
  205. p3d_2,
  206. p3d_3,
  207. p3d_centre;
  208. double longar[3],
  209. longp1p2,
  210. longp1p3,
  211. longp2p3;
  212. free (*listcentre);
  213. *listcentre = (point3d *) malloc (nbfaces * sizeof (point3d));
  214. a2ri_erreur_critique_si (*listcentre == NULL,
  215. "erreur allocation memoire pour listcentre\na2ri_vf_bounding_ball_minimale");
  216. for (int alpha = 0; alpha < nbfaces; alpha++)
  217. {
  218. ve1 = m->fa[faces[alpha]].ve1;
  219. ve2 = m->fa[faces[alpha]].ve2;
  220. ve3 = m->fa[faces[alpha]].ve3;
  221. point3d_init (&p3d_1, m->ve[ve1].x, m->ve[ve1].y, m->ve[ve1].z);
  222. point3d_init (&p3d_2, m->ve[ve2].x, m->ve[ve2].y, m->ve[ve2].z);
  223. point3d_init (&p3d_3, m->ve[ve3].x, m->ve[ve3].y, m->ve[ve3].z);
  224. longar[0] = point3d_square_length (&p3d_1, &p3d_2);
  225. longp1p2 = longar[0];
  226. longar[1] = point3d_square_length (&p3d_1, &p3d_3);
  227. longp1p3 = longar[1];
  228. longar[2] = point3d_square_length (&p3d_2, &p3d_3);
  229. longp2p3 = longar[2];
  230. list_double_sort (longar, 3, ASC);
  231. if (longar[2] > longar[0] + longar[1])
  232. {
  233. if (longar[2] == longp1p2)
  234. {
  235. (*listcentre)[alpha].x = ((p3d_1.x + p3d_2.x) * 1.0) / 2.0;
  236. (*listcentre)[alpha].y = ((p3d_1.y + p3d_2.y) * 1.0) / 2.0;
  237. (*listcentre)[alpha].z = ((p3d_1.z + p3d_2.z) * 1.0) / 2.0;
  238. }
  239. if (longar[2] == longp1p3)
  240. {
  241. (*listcentre)[alpha].x = ((p3d_1.x + p3d_3.x) * 1.0) / 2.0;
  242. (*listcentre)[alpha].y = ((p3d_1.y + p3d_3.y) * 1.0) / 2.0;
  243. (*listcentre)[alpha].z = ((p3d_1.z + p3d_3.z) * 1.0) / 2.0;
  244. }
  245. if (longar[2] == longp2p3)
  246. {
  247. (*listcentre)[alpha].x = ((p3d_2.x + p3d_3.x) * 1.0) / 2.0;
  248. (*listcentre)[alpha].y = ((p3d_2.y + p3d_3.y) * 1.0) / 2.0;
  249. (*listcentre)[alpha].z = ((p3d_2.z + p3d_3.z) * 1.0) / 2.0;
  250. }
  251. list_double_add (listradius, &nbelt, sqrt (longar[2]) / 2.0,
  252. WITH_REDUNDANCE);
  253. }
  254. else
  255. {
  256. p3d_centre = circumcircle_center (&p3d_1, &p3d_2, &p3d_3);
  257. x = p3d_centre.x;
  258. y = p3d_centre.y;
  259. z = p3d_centre.z;
  260. radius = sqrt ((m->ve[ve1].x - x) * (m->ve[ve1].x - x) +
  261. (m->ve[ve1].y - y) * (m->ve[ve1].y - y) +
  262. (m->ve[ve1].z - z) * (m->ve[ve1].z - z));
  263. (*listcentre)[alpha].x = x;
  264. (*listcentre)[alpha].y = y;
  265. (*listcentre)[alpha].z = z;
  266. list_double_add (listradius, &nbelt, radius, WITH_REDUNDANCE);
  267. }
  268. }
  269. }
  270. /**
  271. Calcul l'oriented bounding box du maillage
  272. @param m le modèle
  273. @param newbasex pointeur sur le vecteur "X" de la nouvelle base dans laquelle l'oriented bounding box est représenté
  274. @param newbasey pointeur sur le vecteur "Y" de la nouvelle base dans laquelle l'oriented bounding box est représenté
  275. @param newbasez pointeur sur le vecteur "Z" de la nouvelle base dans laquelle l'oriented bounding box est représenté
  276. @param ptmin pointeur sur le point3d contenant le coin inférieur de l'oriented bounding box
  277. @param ptmax pointeur sur le point3d contenant le coin supérieur de l'oriented bounding box
  278. **/
  279. void
  280. a2ri_vf_oriented_bounding_box (
  281. const vf_model * const m,
  282. vector3d * newbasex,
  283. vector3d * newbasey,
  284. vector3d * newbasez,
  285. point3d * ptmin,
  286. point3d * ptmax)
  287. {
  288. point3d *listsommet = NULL;
  289. gsl_matrix *covariance,
  290. *matpass = NULL,
  291. *point,
  292. *res = NULL;
  293. double data[9];
  294. gsl_vector *eval = gsl_vector_alloc (3);
  295. a2ri_erreur_critique_si (eval == NULL,
  296. "erreur allocation memoire pour eval\na2ri_vf_oriented_bounding_box");
  297. gsl_matrix *evec = gsl_matrix_alloc (3, 3);
  298. a2ri_erreur_critique_si (evec == NULL,
  299. "erreur allocation memoire pour evec\na2ri_vf_oriented_bounding_box");
  300. gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc (3);
  301. a2ri_erreur_critique_si (w == NULL,
  302. "erreur allocation memoire pour w\na2ri_vf_oriented_bounding_box");
  303. gsl_vector_view evec_i;
  304. point = gsl_matrix_alloc (1, 3);
  305. a2ri_erreur_critique_si (point == NULL,
  306. "erreur allocation memoire pour point\na2ri_vf_oriented_bounding_box");
  307. //calcul de la matrice de covariance
  308. listsommet = (point3d *) malloc (m->nbvertex * sizeof (point3d));
  309. a2ri_erreur_critique_si (listsommet == NULL,
  310. "erreur allocation memoire pour listsommet\na2ri_vf_oriented_bounding_box");
  311. for (int i = 0; i < m->nbvertex; i++)
  312. point3d_init (&(listsommet[i]), m->ve[i].x, m->ve[i].y, m->ve[i].z);
  313. covariance = cross_variance (listsommet, listsommet, m->nbvertex);
  314. //calcul des vecteurs propres qui seront les directions principales de la faces
  315. gsl_eigen_symmv (covariance, eval, evec, w);
  316. //récupération du premier vecteur propre
  317. evec_i = gsl_matrix_column (evec, 0);
  318. //affectation du nouveau vecteur "X" dans newbasex
  319. newbasex->dx = gsl_vector_get (&evec_i.vector, 0);
  320. newbasex->dy = gsl_vector_get (&evec_i.vector, 1);
  321. newbasex->dz = gsl_vector_get (&evec_i.vector, 2);
  322. data[0] = gsl_vector_get (&evec_i.vector, 0);
  323. data[3] = gsl_vector_get (&evec_i.vector, 1);
  324. data[6] = gsl_vector_get (&evec_i.vector, 2);
  325. //récupération du second vecteur propre
  326. evec_i = gsl_matrix_column (evec, 1);
  327. //affectation du nouveau vecteur "Y" dans newbasey
  328. newbasey->dx = gsl_vector_get (&evec_i.vector, 0);
  329. newbasey->dy = gsl_vector_get (&evec_i.vector, 1);
  330. newbasey->dz = gsl_vector_get (&evec_i.vector, 2);
  331. data[1] = gsl_vector_get (&evec_i.vector, 0);
  332. data[4] = gsl_vector_get (&evec_i.vector, 1);
  333. data[7] = gsl_vector_get (&evec_i.vector, 2);
  334. //récupération du troisième vecteur propre
  335. evec_i = gsl_matrix_column (evec, 2);
  336. //affectation du nouveau vecteur "Z" dans newbaseZ
  337. newbasez->dx = gsl_vector_get (&evec_i.vector, 0);
  338. newbasez->dy = gsl_vector_get (&evec_i.vector, 1);
  339. newbasez->dz = gsl_vector_get (&evec_i.vector, 2);
  340. data[2] = gsl_vector_get (&evec_i.vector, 0);
  341. data[5] = gsl_vector_get (&evec_i.vector, 1);
  342. data[8] = gsl_vector_get (&evec_i.vector, 2);
  343. //construction de la matrice de passage de l'ancienne à la nouvelle base
  344. matpass = matrix_init (data, 3, 3);
  345. //calcul des nouvelles coordonnées du premier sommet et mise à jour des coins inférieurs et supérieurs dans ptmin et ptmax
  346. gsl_matrix_set (point, 0, 0, m->ve[0].x);
  347. gsl_matrix_set (point, 0, 1, m->ve[0].y);
  348. gsl_matrix_set (point, 0, 2, m->ve[0].z);
  349. res = matrix_mul (point, matpass);
  350. ptmin->x = gsl_matrix_get (res, 0, 0);
  351. ptmax->x = gsl_matrix_get (res, 0, 0);
  352. ptmin->y = gsl_matrix_get (res, 0, 1);
  353. ptmax->y = gsl_matrix_get (res, 0, 1);
  354. ptmin->z = gsl_matrix_get (res, 0, 2);
  355. ptmax->z = gsl_matrix_get (res, 0, 2);
  356. //calcul des nouvelles coordonnées des autres sommets et mise à jour des coins inférieurs et supérieurs dans ptmin et ptmax
  357. for (int i = 1; i < m->nbvertex; i++)
  358. {
  359. gsl_matrix_set (point, 0, 0, m->ve[i].x);
  360. gsl_matrix_set (point, 0, 1, m->ve[i].y);
  361. gsl_matrix_set (point, 0, 2, m->ve[i].z);
  362. res = matrix_mul (point, matpass);
  363. if (ptmin->x > gsl_matrix_get (res, 0, 0))
  364. ptmin->x = gsl_matrix_get (res, 0, 0);
  365. if (ptmax->x < gsl_matrix_get (res, 0, 0))
  366. ptmax->x = gsl_matrix_get (res, 0, 0);
  367. if (ptmin->y > gsl_matrix_get (res, 0, 1))
  368. ptmin->y = gsl_matrix_get (res, 0, 1);
  369. if (ptmax->y < gsl_matrix_get (res, 0, 1))
  370. ptmax->y = gsl_matrix_get (res, 0, 1);
  371. if (ptmin->z > gsl_matrix_get (res, 0, 2))
  372. ptmin->z = gsl_matrix_get (res, 0, 2);
  373. if (ptmax->z < gsl_matrix_get (res, 0, 2))
  374. ptmax->z = gsl_matrix_get (res, 0, 2);
  375. }
  376. gsl_matrix_free (covariance);
  377. gsl_matrix_free (matpass);
  378. gsl_matrix_free (point);
  379. gsl_matrix_free (res);
  380. gsl_eigen_symmv_free (w);
  381. }
  382. /**
  383. Calcul des sphères englobantes des faces de la liste
  384. @param m le modèle
  385. @param faces tableau contenant les numéros des faces pour lesquels on veut les sphères englobantes
  386. @param nbfaces taille du tableau
  387. @param listcentre pointeur sur le tableau de point3d contenant les centres de sphères englobantes
  388. @param listradius pointeur sur le tableau contenant les rayons des sphères englobantes
  389. **/
  390. void
  391. a2ri_vef_bounding_ball_minimale (
  392. const vef_model * const m,
  393. const int * const faces,
  394. int nbfaces,
  395. point3d ** listcentre,
  396. double **listradius)
  397. {
  398. double radius,
  399. x,
  400. y,
  401. z;
  402. int ve1,
  403. ve2,
  404. ve3,
  405. nbelt = 0;
  406. point3d p3d_1,
  407. p3d_2,
  408. p3d_3,
  409. p3d_centre;
  410. double longar[3],
  411. longp1p2,
  412. longp1p3,
  413. longp2p3;
  414. free (*listcentre);
  415. *listcentre = (point3d *) malloc (nbfaces * sizeof (point3d));
  416. a2ri_erreur_critique_si (*listcentre == NULL,
  417. "erreur allocation memoire pour listcentre\na2ri_vef_bounding_ball_minimale");
  418. for (int alpha = 0; alpha < nbfaces; alpha++)
  419. {
  420. vef_face_get_vertices (&(m->fa[faces[alpha]]), m->ed, &ve1, &ve2, &ve3);
  421. point3d_init (&p3d_1, m->ve[ve1].x, m->ve[ve1].y, m->ve[ve1].z);
  422. point3d_init (&p3d_2, m->ve[ve2].x, m->ve[ve2].y, m->ve[ve2].z);
  423. point3d_init (&p3d_3, m->ve[ve3].x, m->ve[ve3].y, m->ve[ve3].z);
  424. longar[0] = point3d_square_length (&p3d_1, &p3d_2);
  425. longp1p2 = longar[0];
  426. longar[1] = point3d_square_length (&p3d_1, &p3d_3);
  427. longp1p3 = longar[1];
  428. longar[2] = point3d_square_length (&p3d_2, &p3d_3);
  429. longp2p3 = longar[2];
  430. list_double_sort (longar, 3, ASC);
  431. if (longar[2] > longar[0] + longar[1])
  432. {
  433. if (longar[2] == longp1p2)
  434. {
  435. (*listcentre)[alpha].x = ((p3d_1.x + p3d_2.x) * 1.0) / 2.0;
  436. (*listcentre)[alpha].y = ((p3d_1.y + p3d_2.y) * 1.0) / 2.0;
  437. (*listcentre)[alpha].z = ((p3d_1.z + p3d_2.z) * 1.0) / 2.0;
  438. }
  439. if (longar[2] == longp1p3)
  440. {
  441. (*listcentre)[alpha].x = ((p3d_1.x + p3d_3.x) * 1.0) / 2.0;
  442. (*listcentre)[alpha].y = ((p3d_1.y + p3d_3.y) * 1.0) / 2.0;
  443. (*listcentre)[alpha].z = ((p3d_1.z + p3d_3.z) * 1.0) / 2.0;
  444. }
  445. if (longar[2] == longp2p3)
  446. {
  447. (*listcentre)[alpha].x = ((p3d_2.x + p3d_3.x) * 1.0) / 2.0;
  448. (*listcentre)[alpha].y = ((p3d_2.y + p3d_3.y) * 1.0) / 2.0;
  449. (*listcentre)[alpha].z = ((p3d_2.z + p3d_3.z) * 1.0) / 2.0;
  450. }
  451. list_double_add (listradius, &nbelt, sqrt (longar[2]) / 2.0,
  452. WITH_REDUNDANCE);
  453. }
  454. else
  455. {
  456. p3d_centre = circumcircle_center (&p3d_1, &p3d_2, &p3d_3);
  457. x = p3d_centre.x;
  458. y = p3d_centre.y;
  459. z = p3d_centre.z;
  460. radius = sqrt ((m->ve[ve1].x - x) * (m->ve[ve1].x - x) +
  461. (m->ve[ve1].y - y) * (m->ve[ve1].y - y) +
  462. (m->ve[ve1].z - z) * (m->ve[ve1].z - z));
  463. (*listcentre)[alpha].x = x;
  464. (*listcentre)[alpha].y = y;
  465. (*listcentre)[alpha].z = z;
  466. list_double_add (listradius, &nbelt, radius, WITH_REDUNDANCE);
  467. }
  468. }
  469. }
  470. /**
  471. Calcul des sphères englobantes des faces de la liste
  472. @param m le modèle
  473. @param faces tableau contenant les numéros des faces pour lesquels on veut les sphères englobantes
  474. @param nbfaces taille du tableau
  475. @param listcentre pointeur sur le tableau de point3d contenant les centres de sphères englobantes
  476. @param listradius pointeur sur le tableau contenant les rayons des sphères englobantes
  477. **/
  478. void
  479. point3d_bounding_ball_minimale (
  480. const point3d * const faces,
  481. int nbfaces,
  482. point3d ** listcentre,
  483. double **listradius)
  484. {
  485. double radius,
  486. x,
  487. y,
  488. z;
  489. int nbelt = 0;
  490. point3d p3d_1,
  491. p3d_2,
  492. p3d_3,
  493. p3d_centre;
  494. double longar[3],
  495. longp1p2,
  496. longp1p3,
  497. longp2p3;
  498. free (*listcentre);
  499. *listcentre = (point3d *) malloc (nbfaces * sizeof (point3d));
  500. a2ri_erreur_critique_si (*listcentre == NULL,
  501. "erreur allocation memoire pour lsitcentre\nvef_bounding_ball_minimale");
  502. for (int alpha = 0; alpha < nbfaces; alpha++)
  503. {
  504. point3d_init (&p3d_1, faces[alpha * 3].x, faces[alpha * 3].y,
  505. faces[alpha * 3].z);
  506. point3d_init (&p3d_2, faces[alpha * 3 + 1].x, faces[alpha * 3 + 1].y,
  507. faces[alpha * 3 + 1].z);
  508. point3d_init (&p3d_3, faces[alpha * 3 + 2].x, faces[alpha * 3 + 2].y,
  509. faces[alpha * 3 + 2].z);
  510. longar[0] = point3d_square_length (&p3d_1, &p3d_2);
  511. longp1p2 = longar[0];
  512. longar[1] = point3d_square_length (&p3d_1, &p3d_3);
  513. longp1p3 = longar[1];
  514. longar[2] = point3d_square_length (&p3d_2, &p3d_3);
  515. longp2p3 = longar[2];
  516. list_double_sort (longar, 3, ASC);
  517. if (longar[2] > longar[0] + longar[1])
  518. {
  519. if (longar[2] == longp1p2)
  520. {
  521. (*listcentre)[alpha].x = ((p3d_1.x + p3d_2.x) * 1.0) / 2.0;
  522. (*listcentre)[alpha].y = ((p3d_1.y + p3d_2.y) * 1.0) / 2.0;
  523. (*listcentre)[alpha].z = ((p3d_1.z + p3d_2.z) * 1.0) / 2.0;
  524. }
  525. if (longar[2] == longp1p3)
  526. {
  527. (*listcentre)[alpha].x = ((p3d_1.x + p3d_3.x) * 1.0) / 2.0;
  528. (*listcentre)[alpha].y = ((p3d_1.y + p3d_3.y) * 1.0) / 2.0;
  529. (*listcentre)[alpha].z = ((p3d_1.z + p3d_3.z) * 1.0) / 2.0;
  530. }
  531. if (longar[2] == longp2p3)
  532. {
  533. (*listcentre)[alpha].x = ((p3d_2.x + p3d_3.x) * 1.0) / 2.0;
  534. (*listcentre)[alpha].y = ((p3d_2.y + p3d_3.y) * 1.0) / 2.0;
  535. (*listcentre)[alpha].z = ((p3d_2.z + p3d_3.z) * 1.0) / 2.0;
  536. }
  537. list_double_add (listradius, &nbelt, sqrt (longar[2]) / 2.0,
  538. WITH_REDUNDANCE);
  539. }
  540. else
  541. {
  542. p3d_centre = circumcircle_center (&p3d_1, &p3d_2, &p3d_3);
  543. x = p3d_centre.x;
  544. y = p3d_centre.y;
  545. z = p3d_centre.z;
  546. radius = sqrt ((p3d_1.x - x) * (p3d_1.x - x) +
  547. (p3d_1.y - y) * (p3d_1.y - y) +
  548. (p3d_1.z - z) * (p3d_1.z - z));
  549. (*listcentre)[alpha].x = x;
  550. (*listcentre)[alpha].y = y;
  551. (*listcentre)[alpha].z = z;
  552. list_double_add (listradius, &nbelt, radius, WITH_REDUNDANCE);
  553. }
  554. }
  555. }