graph.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*************************************/
  2. /* Auteur : Rémi Synave */
  3. /* Date de création : 05/01/08 */
  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 "graph.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. int IFlist_edge_etape_tri_rapide (
  29. double *listlong,
  30. int *listnumedge,
  31. int min,
  32. int max)
  33. {
  34. double temp = listlong[max];
  35. int temp2 = listnumedge[max];
  36. while (max > min)
  37. {
  38. while (max > min && listlong[min] <= temp)
  39. min++;
  40. if (max > min)
  41. {
  42. listlong[max] = listlong[min];
  43. listnumedge[max] = listnumedge[min];
  44. max--;
  45. while (max > min && listlong[max] >= temp)
  46. max--;
  47. if (max > min)
  48. {
  49. listlong[min] = listlong[max];
  50. listnumedge[min] = listnumedge[max];
  51. min++;
  52. }
  53. }
  54. }
  55. listlong[max] = temp;
  56. listnumedge[max] = temp2;
  57. return (max);
  58. }
  59. void IFlist_edge_tri_rapide (
  60. double *listlong,
  61. int *listnumedge,
  62. int deb,
  63. int fin)
  64. {
  65. int mil;
  66. if (deb < fin)
  67. {
  68. mil = IFlist_edge_etape_tri_rapide (listlong, listnumedge, deb, fin);
  69. if (mil - deb > fin - mil)
  70. {
  71. IFlist_edge_tri_rapide (listlong, listnumedge, mil + 1, fin);
  72. IFlist_edge_tri_rapide (listlong, listnumedge, deb, mil - 1);
  73. }
  74. else
  75. {
  76. IFlist_edge_tri_rapide (listlong, listnumedge, deb, mil - 1);
  77. IFlist_edge_tri_rapide (listlong, listnumedge, mil + 1, fin);
  78. }
  79. }
  80. }
  81. void
  82. IFlist_edge_sort (
  83. double *listlong,
  84. int *listnumedge,
  85. int size)
  86. {
  87. IFlist_edge_tri_rapide (listlong, listnumedge, 0, size - 1);
  88. }
  89. /********** MAIN FUNCTIONS **********/
  90. /**
  91. Calcul du graphe Nearest Neighbour Graph (NNG)
  92. @param m le modele
  93. @return un modele contenant les aretes
  94. */
  95. vef_model *
  96. a2ri_vef_nearest_neighbour_graph (
  97. const vef_model * const m)
  98. {
  99. point3d p1,
  100. p2,
  101. ptmin,
  102. ptmax;
  103. double distmin;
  104. space_partition sp;
  105. vef_model *retour = (vef_model *) malloc (sizeof (vef_model));
  106. a2ri_erreur_critique_si (retour == NULL,
  107. "erreur allocation memoire pour retour\na2ri_vef_nearest_neighbour_graph");
  108. a2ri_vef_init (retour);
  109. for (int i = 0; i < m->nbvertex; i++)
  110. a2ri_vef_add_vertex (retour, m->ve[i].x, m->ve[i].y, m->ve[i].z);
  111. point3d_init (&ptmin, m->xmin, m->ymin, m->zmin);
  112. point3d_init (&ptmax, m->xmax, m->ymax, m->zmax);
  113. space_partition_new (&sp, &ptmin, &ptmax, 8, 8, 8);
  114. a2ri_vef_space_partition (m, &sp);
  115. retour->xmin = m->xmin;
  116. retour->xmax = m->xmax;
  117. retour->ymin = m->ymin;
  118. retour->ymax = m->ymax;
  119. retour->zmin = m->zmin;
  120. retour->zmax = m->zmax;
  121. for (int i = 0; i < m->nbvertex; i++)
  122. {
  123. point3d_init (&p1, m->ve[i].x, m->ve[i].y, m->ve[i].z);
  124. space_partition_nearest_point (&sp, &p1, &p2, &distmin,
  125. REJECT_ZERO_LENGTH);
  126. a2ri_vef_add_edge (retour, i, p2.att_int, 1);
  127. }
  128. space_partition_free (&sp);
  129. return retour;
  130. }
  131. /**
  132. Calcul du graphe Gabriel (GG)
  133. @param m le modele
  134. @return un modele contenant les aretes
  135. */
  136. vef_model *
  137. a2ri_vef_gabriel_graph (
  138. const vef_model * const m)
  139. {
  140. point3d p,
  141. centre;
  142. double distance;
  143. int alinterieur,
  144. k;
  145. vef_model *retour = (vef_model *) malloc (sizeof (vef_model));
  146. a2ri_erreur_critique_si (retour == NULL,
  147. "erreur allocation memoire pour retour\na2ri_vef_gabriel_graph");
  148. a2ri_vef_init (retour);
  149. for (int i = 0; i < m->nbvertex; i++)
  150. a2ri_vef_add_vertex (retour, m->ve[i].x, m->ve[i].y, m->ve[i].z);
  151. retour->xmin = m->xmin;
  152. retour->xmax = m->xmax;
  153. retour->ymin = m->ymin;
  154. retour->ymax = m->ymax;
  155. retour->zmin = m->zmin;
  156. retour->zmax = m->zmax;
  157. for (int i = 0; i < m->nbvertex; i++)
  158. {
  159. for (int j = 0; j < m->nbvertex; j++)
  160. if (i != j)
  161. {
  162. point3d_init (&centre,
  163. ((m->ve[i].x + m->ve[j].x) * 1.0) / 2.0,
  164. ((m->ve[i].y + m->ve[j].y) * 1.0) / 2.0,
  165. ((m->ve[i].z + m->ve[j].z) * 1.0) / 2.0);
  166. point3d_init (&p, m->ve[i].x, m->ve[i].y, m->ve[i].z);
  167. distance = point3d_length (&centre, &p);
  168. alinterieur = 0;
  169. k = 0;
  170. while (k < m->nbvertex && alinterieur == 0)
  171. {
  172. if (k != i && k != j)
  173. {
  174. point3d_init (&p, m->ve[k].x, m->ve[k].y, m->ve[k].z);
  175. if (point3d_length (&p, &centre) < distance)
  176. alinterieur++;
  177. }
  178. k++;
  179. }
  180. if (!alinterieur)
  181. a2ri_vef_add_edge (retour, i, j, 1);
  182. }
  183. }
  184. return retour;
  185. }
  186. /**
  187. Calcul du graphe etendu Gabriel (NNG)
  188. @param m le modele
  189. @return un modele contenant les aretes
  190. */
  191. vef_model *
  192. a2ri_vef_extended_gabriel_hypergraph (
  193. const vef_model * const m)
  194. {
  195. vef_model *retour = a2ri_vef_gabriel_graph (m);
  196. int *listve = NULL,
  197. size = 0,
  198. ve1,
  199. ve2,
  200. ve3;
  201. point3d p[3],
  202. *centre = NULL;
  203. double *rayon = NULL;
  204. int trouve,
  205. k;
  206. vector3d AB,
  207. AC;
  208. /*PARTIE1 */
  209. for (int i = 0; i < retour->nbedge; i++)
  210. {
  211. for (int j = 0; j < retour->nbedge; j++)
  212. {
  213. listve = NULL;
  214. size = 0;
  215. list_int_add (&listve, &size, retour->ed[i].ve1,
  216. WITHOUT_REDUNDANCE);
  217. list_int_add (&listve, &size, retour->ed[i].ve2,
  218. WITHOUT_REDUNDANCE);
  219. list_int_add (&listve, &size, retour->ed[j].ve1,
  220. WITHOUT_REDUNDANCE);
  221. list_int_add (&listve, &size, retour->ed[j].ve2,
  222. WITHOUT_REDUNDANCE);
  223. if (size == 3)
  224. {
  225. vector3d_init (&AB,
  226. retour->ve[listve[0]].x -
  227. retour->ve[listve[1]].x,
  228. retour->ve[listve[0]].y -
  229. retour->ve[listve[1]].y,
  230. retour->ve[listve[0]].z -
  231. retour->ve[listve[1]].z);
  232. vector3d_init (&AC,
  233. retour->ve[listve[0]].x -
  234. retour->ve[listve[2]].x,
  235. retour->ve[listve[0]].y -
  236. retour->ve[listve[2]].y,
  237. retour->ve[listve[0]].z -
  238. retour->ve[listve[2]].z);
  239. double coeff = AB.dx / AC.dx;
  240. AC.dx *= coeff;
  241. AC.dy *= coeff;
  242. AC.dz *= coeff;
  243. if (!vector3d_equal (&AB, &AC))
  244. {
  245. ve1 = retour->ed[i].ve1;
  246. ve2 = retour->ed[i].ve2;
  247. if (!(ve2 == retour->ed[j].ve1 || ve2 == retour->ed[j].ve2))
  248. {
  249. ve3 = ve1;
  250. ve1 = ve2;
  251. ve2 = ve3;
  252. }
  253. if (ve2 == retour->ed[j].ve1)
  254. ve3 = retour->ed[j].ve2;
  255. else
  256. ve3 = retour->ed[j].ve1;
  257. if (a2ri_vef_search_edge (retour, ve1, ve3) == -1)
  258. {
  259. point3d_init (&(p[0]), retour->ve[ve1].x,
  260. retour->ve[ve1].y, retour->ve[ve1].z);
  261. point3d_init (&(p[1]), retour->ve[ve2].x,
  262. retour->ve[ve2].y, retour->ve[ve2].z);
  263. point3d_init (&(p[2]), retour->ve[ve3].x,
  264. retour->ve[ve3].y, retour->ve[ve3].z);
  265. centre = NULL;
  266. rayon = NULL;
  267. point3d_bounding_ball_minimale (p, 1, &centre, &rayon);
  268. trouve = 0;
  269. k = 0;
  270. while (k < retour->nbvertex && !trouve)
  271. {
  272. point3d_init (&(p[0]), retour->ve[k].x,
  273. retour->ve[k].y, retour->ve[k].z);
  274. if (point3d_length (&(p[0]), &(centre[0])) < rayon[0])
  275. trouve = 1;
  276. k++;
  277. }
  278. if (!trouve)
  279. a2ri_vef_add_edge (retour, ve1, ve3, 0);
  280. free (centre);
  281. free (rayon);
  282. }
  283. }
  284. }
  285. free (listve);
  286. }
  287. }
  288. /*PARTIE2 */
  289. for (int i = 0; i < retour->nbedge; i++)
  290. {
  291. int numvertex_a = retour->ed[i].ve1;
  292. for (int j = 0; j < retour->ve[numvertex_a].nbsharededges; j++)
  293. {
  294. int numedge_a = retour->ve[numvertex_a].sharededges[j];
  295. int numvertex_b = retour->ed[numedge_a].ve1;
  296. for (k = 0; k < retour->ve[numvertex_b].nbsharededges; k++)
  297. {
  298. int numedge_b = retour->ve[numvertex_b].sharededges[k];
  299. if (i != numedge_a && i != numedge_b && numedge_a != numedge_b)
  300. {
  301. listve = NULL;
  302. size = 0;
  303. list_int_add (&listve, &size, retour->ed[i].ve1,
  304. WITHOUT_REDUNDANCE);
  305. list_int_add (&listve, &size, retour->ed[i].ve2,
  306. WITHOUT_REDUNDANCE);
  307. list_int_add (&listve, &size, retour->ed[numedge_a].ve1,
  308. WITHOUT_REDUNDANCE);
  309. list_int_add (&listve, &size, retour->ed[numedge_a].ve2,
  310. WITHOUT_REDUNDANCE);
  311. list_int_add (&listve, &size, retour->ed[numedge_b].ve1,
  312. WITHOUT_REDUNDANCE);
  313. list_int_add (&listve, &size, retour->ed[numedge_b].ve2,
  314. WITHOUT_REDUNDANCE);
  315. if (size == 3)
  316. {
  317. if (a2ri_vef_search_face
  318. (retour, i, numedge_a, numedge_b) == -1
  319. && a2ri_vef_search_face (retour, i, numedge_b,
  320. numedge_a) == -1)
  321. a2ri_vef_add_face (retour, i, numedge_a, numedge_b);
  322. }
  323. free (listve);
  324. }
  325. }
  326. numvertex_b = retour->ed[numedge_a].ve2;
  327. for (k = 0; k < retour->ve[numvertex_b].nbsharededges; k++)
  328. {
  329. int numedge_b = retour->ve[numvertex_b].sharededges[k];
  330. if (i != numedge_a && i != numedge_b && numedge_a != numedge_b)
  331. {
  332. listve = NULL;
  333. size = 0;
  334. list_int_add (&listve, &size, retour->ed[i].ve1,
  335. WITHOUT_REDUNDANCE);
  336. list_int_add (&listve, &size, retour->ed[i].ve2,
  337. WITHOUT_REDUNDANCE);
  338. list_int_add (&listve, &size, retour->ed[numedge_a].ve1,
  339. WITHOUT_REDUNDANCE);
  340. list_int_add (&listve, &size, retour->ed[numedge_a].ve2,
  341. WITHOUT_REDUNDANCE);
  342. list_int_add (&listve, &size, retour->ed[numedge_b].ve1,
  343. WITHOUT_REDUNDANCE);
  344. list_int_add (&listve, &size, retour->ed[numedge_b].ve2,
  345. WITHOUT_REDUNDANCE);
  346. if (size == 3)
  347. {
  348. if (a2ri_vef_search_face
  349. (retour, i, numedge_a, numedge_b) == -1
  350. && a2ri_vef_search_face (retour, i, numedge_b,
  351. numedge_a) == -1)
  352. a2ri_vef_add_face (retour, i, numedge_a, numedge_b);
  353. }
  354. free (listve);
  355. }
  356. }
  357. }
  358. //IDEM POUR LE SECOND POINT
  359. numvertex_a = retour->ed[i].ve2;
  360. for (int j = 0; j < retour->ve[numvertex_a].nbsharededges; j++)
  361. {
  362. int numedge_a = retour->ve[numvertex_a].sharededges[j];
  363. int numvertex_b = retour->ed[numedge_a].ve1;
  364. for (k = 0; k < retour->ve[numvertex_b].nbsharededges; k++)
  365. {
  366. int numedge_b = retour->ve[numvertex_b].sharededges[k];
  367. if (i != numedge_a && i != numedge_b && numedge_a != numedge_b)
  368. {
  369. listve = NULL;
  370. size = 0;
  371. list_int_add (&listve, &size, retour->ed[i].ve1,
  372. WITHOUT_REDUNDANCE);
  373. list_int_add (&listve, &size, retour->ed[i].ve2,
  374. WITHOUT_REDUNDANCE);
  375. list_int_add (&listve, &size, retour->ed[numedge_a].ve1,
  376. WITHOUT_REDUNDANCE);
  377. list_int_add (&listve, &size, retour->ed[numedge_a].ve2,
  378. WITHOUT_REDUNDANCE);
  379. list_int_add (&listve, &size, retour->ed[numedge_b].ve1,
  380. WITHOUT_REDUNDANCE);
  381. list_int_add (&listve, &size, retour->ed[numedge_b].ve2,
  382. WITHOUT_REDUNDANCE);
  383. if (size == 3)
  384. {
  385. if (a2ri_vef_search_face
  386. (retour, i, numedge_a, numedge_b) == -1
  387. && a2ri_vef_search_face (retour, i, numedge_b,
  388. numedge_a) == -1)
  389. a2ri_vef_add_face (retour, i, numedge_a, numedge_b);
  390. }
  391. free (listve);
  392. }
  393. }
  394. numvertex_b = retour->ed[numedge_a].ve2;
  395. for (k = 0; k < retour->ve[numvertex_b].nbsharededges; k++)
  396. {
  397. int numedge_b = retour->ve[numvertex_b].sharededges[k];
  398. if (i != numedge_a && i != numedge_b && numedge_a != numedge_b)
  399. {
  400. listve = NULL;
  401. size = 0;
  402. list_int_add (&listve, &size, retour->ed[i].ve1,
  403. WITHOUT_REDUNDANCE);
  404. list_int_add (&listve, &size, retour->ed[i].ve2,
  405. WITHOUT_REDUNDANCE);
  406. list_int_add (&listve, &size, retour->ed[numedge_a].ve1,
  407. WITHOUT_REDUNDANCE);
  408. list_int_add (&listve, &size, retour->ed[numedge_a].ve2,
  409. WITHOUT_REDUNDANCE);
  410. list_int_add (&listve, &size, retour->ed[numedge_b].ve1,
  411. WITHOUT_REDUNDANCE);
  412. list_int_add (&listve, &size, retour->ed[numedge_b].ve2,
  413. WITHOUT_REDUNDANCE);
  414. if (size == 3)
  415. {
  416. if (a2ri_vef_search_face
  417. (retour, i, numedge_a, numedge_b) == -1
  418. && a2ri_vef_search_face (retour, i, numedge_b,
  419. numedge_a) == -1)
  420. a2ri_vef_add_face (retour, i, numedge_a, numedge_b);
  421. }
  422. free (listve);
  423. }
  424. }
  425. }
  426. }
  427. return retour;
  428. }
  429. /**
  430. Calcul du graphe recouvrant minimal (EMST - Euclidean Minimal Spanning Tree)
  431. @param m le modele
  432. @return un modele contenant les aretes
  433. */
  434. vef_model *
  435. a2ri_vef_euclidean_minimal_spanning_tree (
  436. const vef_model * const m)
  437. {
  438. int *listedge = NULL,
  439. sizelistedge = 0,
  440. sizelistlongueur = 0;
  441. double *listlongueur = NULL;
  442. point3d p1,
  443. p2;
  444. vef_model *retour = (vef_model *) malloc (sizeof (vef_model));
  445. a2ri_erreur_critique_si (retour == NULL,
  446. "erreur allocation memoire pour retour\na2ri_vef_euclidean_minimal_spanning_tree");
  447. int *vnew = NULL,
  448. sizevnew = 0;
  449. int k,
  450. trouve,
  451. contve1,
  452. contve2;
  453. a2ri_vef_init (retour);
  454. for (int i = 0; i < m->nbvertex; i++)
  455. a2ri_vef_add_vertex (retour, m->ve[i].x, m->ve[i].y, m->ve[i].z);
  456. retour->xmin = m->xmin;
  457. retour->xmax = m->xmax;
  458. retour->ymin = m->ymin;
  459. retour->ymax = m->ymax;
  460. retour->zmin = m->zmin;
  461. retour->zmax = m->zmax;
  462. for (int i = 0; i < m->nbedge; i++)
  463. {
  464. point3d_init (&p1, m->ve[m->ed[i].ve1].x, m->ve[m->ed[i].ve1].y,
  465. m->ve[m->ed[i].ve1].z);
  466. point3d_init (&p2, m->ve[m->ed[i].ve2].x, m->ve[m->ed[i].ve2].y,
  467. m->ve[m->ed[i].ve2].z);
  468. list_int_add (&listedge, &sizelistedge, i, WITH_REDUNDANCE);
  469. list_double_add (&listlongueur, &sizelistlongueur,
  470. point3d_length (&p1, &p2), WITH_REDUNDANCE);
  471. }
  472. IFlist_edge_sort (listlongueur, listedge, sizelistedge);
  473. free (listlongueur);
  474. // Ajout du premier sommet dans la liste
  475. list_int_add (&vnew, &sizevnew, 0, WITH_REDUNDANCE);
  476. while (sizevnew != m->nbvertex)
  477. {
  478. k = 0;
  479. trouve = 0;
  480. while (!trouve)
  481. {
  482. do
  483. {
  484. contve1 =
  485. list_int_contains (vnew, sizevnew, m->ed[listedge[k]].ve1);
  486. contve2 =
  487. list_int_contains (vnew, sizevnew, m->ed[listedge[k]].ve2);
  488. k++;
  489. }
  490. while (contve1 == -1 && contve2 == -1);
  491. k--;
  492. if (contve1 != -1 && contve2 != -1)
  493. list_int_remove (&listedge, &sizelistedge, k);
  494. else
  495. trouve = 1;
  496. }
  497. a2ri_vef_add_edge (retour, m->ed[listedge[k]].ve1,
  498. m->ed[listedge[k]].ve2, 0);
  499. if (contve1 == -1)
  500. list_int_add (&vnew, &sizevnew, m->ed[listedge[k]].ve1,
  501. WITH_REDUNDANCE);
  502. else
  503. list_int_add (&vnew, &sizevnew, m->ed[listedge[k]].ve2,
  504. WITH_REDUNDANCE);
  505. list_int_remove (&listedge, &sizelistedge, k);
  506. }
  507. free (listedge);
  508. free (vnew);
  509. return retour;
  510. }