geometry.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. /*************************************/
  2. /* Auteur : Rémi Synave */
  3. /* Date de création : 01/03/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 "geometry.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. void
  29. IFplanecoeff (
  30. const point3d * const A,
  31. const point3d * const B,
  32. const point3d * const C,
  33. vector3d * N,
  34. double *D)
  35. {
  36. vector3d AB,
  37. AC;
  38. vector3d_init (&AB, B->x - A->x, B->y - A->y, B->z - A->z);
  39. vector3d_init (&AC, C->x - A->x, C->y - A->y, C->z - A->z);
  40. *N = vector3d_vectorialproduct (&AB, &AC);
  41. vector3d_init (&AB, A->x, A->y, A->z);
  42. *D = vector3d_scalarproduct (&AB, N);
  43. }
  44. /********** MAIN FUNCTIONS **********/
  45. /**
  46. Calcul de la longueur entre deux point3d
  47. @param p1 premier point3d
  48. @param p2 second point3d
  49. @return longueur \f$p_1p_2\f$
  50. */
  51. double
  52. point3d_length (
  53. const point3d * const p1,
  54. const point3d * const p2)
  55. {
  56. return sqrt (point3d_square_length (p1, p2));
  57. }
  58. /**
  59. Calcul de la longueur au carré entre deux point3d
  60. @param p1 premier point3d
  61. @param p2 second point3d
  62. @return longueur \f$p_1p_2\f$
  63. */
  64. double
  65. point3d_square_length (
  66. const point3d * const p1,
  67. const point3d * const p2)
  68. {
  69. return (p2->x - p1->x) * (p2->x - p1->x) + (p2->y - p1->y) * (p2->y - p1->y) +
  70. (p2->z - p1->z) * (p2->z - p1->z);
  71. }
  72. /**
  73. Calcul de la longueur entre deux point2d
  74. @param p1 premier point2d
  75. @param p2 second point2d
  76. @return longueur \f$p_1p_2\f$
  77. */
  78. double
  79. point2d_length (
  80. const point2d * const p1,
  81. const point2d * const p2)
  82. {
  83. return sqrt ((p2->x - p1->x) * (p2->x - p1->x) + (p2->y - p1->y) * (p2->y - p1->y));
  84. }
  85. /**
  86. Calcule l'équation d'un plan à partir d'une liste de point sous la forme ax+by+cz+d=0
  87. @param p liste de points
  88. @param size nombre de points
  89. @param aeq valeur de "a"
  90. @param beq valeur de "b"
  91. @param ceq valeur de "c"
  92. @param deq valeur de "d"
  93. @return aucun
  94. Exemple de code
  95. @code
  96. double a,b,c,d;
  97. point3d p[3];
  98. point3d_init(&(p[0]),0.0,0.0,0.0);
  99. point3d_init(&(p[1]),1.0,1.0,-2.0);
  100. point3d_init(&(p[2]),-1.0,1.0,0.0);
  101. equation_plan(p,3,&a,&b,&c,&d);
  102. printf("%dx+%dy+%dz+%d=0\n",a,b,c,d);
  103. @endcode
  104. donne le résultat
  105. @code
  106. 1.0x+1.0y+1.0z+0.0=0
  107. @endcode
  108. */
  109. void
  110. equation_plan (
  111. const point3d * const p,
  112. int size,
  113. double *aeq,
  114. double *beq,
  115. double *ceq,
  116. double *deq)
  117. {
  118. double a = 0;
  119. double b = 0;
  120. double c = 0;
  121. double d = 0;
  122. double xav = 0;
  123. double yav = 0;
  124. double zav = 0;
  125. for (int i = 0; i < size; i++)
  126. {
  127. a += (p[i].y - p[(i + 1) % size].y) * (p[i].z + p[(i + 1) % size].z);
  128. b += (p[i].z - p[(i + 1) % size].z) * (p[i].x + p[(i + 1) % size].x);
  129. c += (p[i].x - p[(i + 1) % size].x) * (p[i].y + p[(i + 1) % size].y);
  130. xav += p[i].x;
  131. yav += p[i].y;
  132. zav += p[i].z;
  133. }
  134. xav /= (size * 1.0);
  135. yav /= (size * 1.0);
  136. zav /= (size * 1.0);
  137. d = -(xav * a + yav * b + zav * c);
  138. *aeq = a;
  139. *beq = b;
  140. *ceq = c;
  141. *deq = d;
  142. }
  143. /**
  144. Calcul de l'aire du triangle défini par les trois points
  145. @param p1 premier point du triangle
  146. @param p2 second point
  147. @param p3 troisième point
  148. @return aire du triangle
  149. */
  150. double
  151. point3d_area (
  152. const point3d * const p1,
  153. const point3d * const p2,
  154. const point3d * const p3)
  155. {
  156. vector3d AB,
  157. AC,
  158. U;
  159. vector3d_init (&AB, p2->x - p1->x, p2->y - p1->y, p2->z - p1->z);
  160. vector3d_init (&AC, p3->x - p1->x, p3->y - p1->y, p3->z - p1->z);
  161. U = vector3d_vectorialproduct (&AB, &AC);
  162. //aire du triangle = 0.5 * norme du produit vectoriel AB AC
  163. return (0.5 * vector3d_size (&U));
  164. }
  165. /**
  166. Transformation des coordonnées d'un point dans un espace à trois dimension en coordonnées dans un espace à deux dimensions dont la base est le couple (base1,base2) et d'origine le point3d "origin"
  167. @param p point dont les coordonnées vont etre recalculées
  168. @param origin point origine du nouveau repére
  169. @param base1 premier vecteur formant la nouvelle base
  170. @param base2 second vecteur formant la nouvelle base
  171. @param newp point contenant les coordonnées dans la nouvelle base
  172. @return aucun
  173. */
  174. void
  175. base_modification_3d_to_2d (
  176. const point3d * const p,
  177. const point3d * const origin,
  178. const vector3d * const base1,
  179. const vector3d * const base2,
  180. point2d * newp)
  181. {
  182. //résolution du système de trois équations à deux inconnues grace à la méthode des moindres carrés
  183. point3d ptemp;
  184. point3d_init(&ptemp,p->x-origin->x,p->y-origin->y,p->z-origin->z);
  185. double left_data[6];
  186. double right_data[3];
  187. left_data[0] = base1->dx;
  188. left_data[1] = base2->dx;
  189. left_data[2] = base1->dy;
  190. left_data[3] = base2->dy;
  191. left_data[4] = base1->dz;
  192. left_data[5] = base2->dz;
  193. right_data[0] = ptemp.x;
  194. right_data[1] = ptemp.y;
  195. right_data[2] = ptemp.z;
  196. gsl_matrix *A = matrix_init (left_data, 3, 2);
  197. gsl_matrix *Y = matrix_init (right_data, 3, 1);
  198. gsl_matrix *transA = matrix_transpose (A);
  199. gsl_matrix *multransAA = matrix_mul (transA, A);
  200. gsl_matrix *invmultransAA = matrix_inverse (multransAA);
  201. gsl_matrix *pseudoinverse = matrix_mul (invmultransAA, transA);
  202. gsl_matrix *inc = matrix_mul (pseudoinverse, Y);
  203. newp->x = gsl_matrix_get (inc, 0, 0);
  204. newp->y = gsl_matrix_get (inc, 1, 0);
  205. gsl_matrix_free (A);
  206. gsl_matrix_free (Y);
  207. gsl_matrix_free (pseudoinverse);
  208. gsl_matrix_free (inc);
  209. gsl_matrix_free (transA);
  210. gsl_matrix_free (multransAA);
  211. gsl_matrix_free (invmultransAA);
  212. }
  213. /**
  214. Calcul du vecteur normal à AB et contenu dans le meme plan que celui formé par les vecteurs (AB,AC). Le résultat final est une base orthogonal du repére.
  215. @param AB premier vecteur de la base
  216. @param AC second vecteur du repére
  217. @param U pointeur sur le nouveau vecteur formant la base orthogonal
  218. */
  219. void
  220. find_second_base_vector (
  221. const vector3d * const AB,
  222. const vector3d * const AC,
  223. vector3d * U)
  224. {
  225. vector3d W,
  226. Utemp;
  227. W = vector3d_vectorialproduct (AB, AC);
  228. Utemp = vector3d_vectorialproduct (&W, AB);
  229. U->dx = Utemp.dx;
  230. U->dy = Utemp.dy;
  231. U->dz = Utemp.dz;
  232. }
  233. /**
  234. Vérification qu'un point M se trouve bien dans le triangle ABC
  235. @param M le point à tester
  236. @param A premier sommet du triangle
  237. @param B second sommet du triangle
  238. @param C troisième sommet du triangle
  239. @return 1 si le point M appartient au triangle ABC, 0 sinon
  240. */
  241. int
  242. point_in_triangle (
  243. const point3d * const M,
  244. const point3d * const A,
  245. const point3d * const B,
  246. const point3d * const C)
  247. {
  248. double sommeangle = 0;
  249. vector3d MA,
  250. MB,
  251. MC;
  252. vector3d_init (&MA, A->x - M->x, A->y - M->y, A->z - M->z);
  253. vector3d_init (&MB, B->x - M->x, B->y - M->y, B->z - M->z);
  254. vector3d_init (&MC, C->x - M->x, C->y - M->y, C->z - M->z);
  255. sommeangle += vector3d_angle_degre (&MA, &MB);
  256. sommeangle += vector3d_angle_degre (&MB, &MC);
  257. sommeangle += vector3d_angle_degre (&MC, &MA);
  258. //le point est contenu dans le triangle si la somme des angles est égale à 360
  259. return (egalite (sommeangle, 360));
  260. }
  261. /**
  262. Calcule l'angle en radian formé par les deux vector3d
  263. @param v1 le premier vector3d
  264. @param v2 le second vector3d
  265. @return angle en radian
  266. */
  267. double
  268. vector3d_angle_radian (
  269. const vector3d * const v1,
  270. const vector3d * const v2)
  271. {
  272. vector3d v1temp,v2temp;
  273. vector3d_init(&v1temp,v1->dx,v1->dy,v1->dz);
  274. vector3d_init(&v2temp,v2->dx,v2->dy,v2->dz);
  275. vector3d_normalize (&v1temp);
  276. vector3d_normalize (&v2temp);
  277. double prodscal = vector3d_scalarproduct (&v1temp, &v2temp);
  278. if (prodscal < -1)
  279. prodscal = -1;
  280. if (prodscal > 1)
  281. prodscal = 1;
  282. return acos (prodscal);
  283. }
  284. /**
  285. Calcule l'angle en degré formé par les deux vector3d
  286. @param v1 le premier vector3d
  287. @param v2 le second vector3d
  288. @return angle en degré
  289. */
  290. double
  291. vector3d_angle_degre (
  292. const vector3d * const v1,
  293. const vector3d * const v2)
  294. {
  295. vector3d v1temp,v2temp;
  296. vector3d_init(&v1temp,v1->dx,v1->dy,v1->dz);
  297. vector3d_init(&v2temp,v2->dx,v2->dy,v2->dz);
  298. vector3d_normalize (&v1temp);
  299. vector3d_normalize (&v2temp);
  300. double prodscal = vector3d_scalarproduct (&v1temp, &v2temp);
  301. if (prodscal < -1)
  302. prodscal = -1;
  303. if (prodscal > 1)
  304. prodscal = 1;
  305. return (acos (prodscal)) * (360 / (2 * PI));
  306. }
  307. /**
  308. Calcule le centre du cercle inscrit à un triangle
  309. @param A premier point du triangle
  310. @param B second point
  311. @param C troisème point
  312. @return le point centre du cercle inscrit
  313. */
  314. point3d
  315. incircle_center (
  316. const point3d * const A,
  317. const point3d * const B,
  318. const point3d * const C)
  319. {
  320. point3d center;
  321. double a = point3d_length (B, C);
  322. double b = point3d_length (A, C);
  323. double c = point3d_length (A, B);
  324. center.x = (a * A->x + b * B->x + c * C->x) / (a + b + c);
  325. center.y = (a * A->y + b * B->y + c * C->y) / (a + b + c);
  326. center.z = (a * A->z + b * B->z + c * C->z) / (a + b + c);
  327. center.att_int = 0;
  328. center.att_double = 0;
  329. return center;
  330. }
  331. /**
  332. Calcule le centre du cercle circonscrit à un triangle
  333. @param A premier point du triangle
  334. @param B second point
  335. @param C troisème point
  336. @return le point centre du cercle inscrit
  337. */
  338. point3d
  339. circumcircle_center (
  340. point3d * A,
  341. point3d * B,
  342. point3d * C)
  343. {
  344. /** méthode du bouquin : 3D Math Pimer for Graphics and Game Development **/
  345. vector3d e1,
  346. e2,
  347. e3,
  348. me1,
  349. me2,
  350. me3;
  351. double d1,
  352. d2,
  353. d3,
  354. c1,
  355. c2,
  356. c3,
  357. c,
  358. alpha,
  359. beta,
  360. gamma;
  361. point3d centre;
  362. vector3d_init (&e1, C->x - B->x, C->y - B->y, C->z - B->z);
  363. vector3d_init (&e2, A->x - C->x, A->y - C->y, A->z - C->z);
  364. vector3d_init (&e3, B->x - A->x, B->y - A->y, B->z - A->z);
  365. vector3d_init (&me1, B->x - C->x, B->y - C->y, B->z - C->z);
  366. vector3d_init (&me2, C->x - A->x, C->y - A->y, C->z - A->z);
  367. vector3d_init (&me3, A->x - B->x, A->y - B->y, A->z - B->z);
  368. d1 = vector3d_scalarproduct (&me2, &e3);
  369. d2 = vector3d_scalarproduct (&me3, &e1);
  370. d3 = vector3d_scalarproduct (&me1, &e2);
  371. c1 = d2 * d3;
  372. c2 = d3 * d1;
  373. c3 = d1 * d2;
  374. c = c1 + c2 + c3;
  375. alpha = (c2 + c3) / (2.0 * c);
  376. beta = (c3 + c1) / (2.0 * c);
  377. gamma = (c1 + c2) / (2.0 * c);
  378. centre.x = (A->x * alpha + B->x * beta + C->x * gamma);
  379. centre.y = (A->y * alpha + B->y * beta + C->y * gamma);
  380. centre.z = (A->z * alpha + B->z * beta + C->z * gamma);
  381. centre.att_double = 0;
  382. centre.att_int = 0;
  383. return centre;
  384. }
  385. /**
  386. Calcule le centre de sphère circonscrite au tétraédre
  387. @param A premier point du tétraédre
  388. @param B second point
  389. @param C troisème point
  390. @param D quatrième point
  391. @return le point centre de la sphère circonscrite
  392. */
  393. point3d
  394. circumsphere_center (
  395. point3d * A,
  396. point3d * B,
  397. point3d * C,
  398. point3d * D)
  399. {
  400. double dataL[9] = { 2 * (B->x - A->x), 2 * (B->y - A->y), 2 * (B->z - A->z),
  401. 2 * (C->x - A->x), 2 * (C->y - A->y), 2 * (C->z - A->z),
  402. 2 * (D->x - A->x), 2 * (D->y - A->y), 2 * (D->z - A->z)
  403. };
  404. double dataR[3] = { point3d_length (A, B) * point3d_length (A, B),
  405. point3d_length (A, C) * point3d_length (A, C),
  406. point3d_length (A, D) * point3d_length (A, D)
  407. };
  408. gsl_matrix *matA = matrix_init (dataL, 3, 3);
  409. gsl_matrix *Y = matrix_init (dataR, 3, 1);
  410. gsl_matrix *pseudoinverse =
  411. matrix_mul (matrix_inverse (matrix_mul (matrix_transpose (matA), matA)),
  412. matrix_transpose (matA));
  413. gsl_matrix *inc = matrix_mul (pseudoinverse, Y);
  414. point3d centre;
  415. point3d_init (&centre, A->x + gsl_matrix_get (inc, 0, 0),
  416. A->y + gsl_matrix_get (inc, 1, 0), A->z + gsl_matrix_get (inc,
  417. 2,
  418. 0));
  419. return centre;
  420. }
  421. /**
  422. Calcule la distance entre un point M et une droite définie par deux points A et B
  423. @param M point
  424. @param A premier point sur la droite
  425. @param B second point sur la droite
  426. @return distance entre le point M et la droite AB
  427. */
  428. double
  429. distance_point_straight_line (
  430. point3d * M,
  431. point3d * A,
  432. point3d * B)
  433. {
  434. double aire = point3d_area (M, A, B);
  435. return (2.0 * aire) / point3d_length (A, B);
  436. }
  437. /**
  438. Calcule la distance entre un point M et un plan définie par trois points A,b et C
  439. @param M point
  440. @param A premier point du plan
  441. @param B second point du plan
  442. @param C troisieme point du plan
  443. @return distance entre le point M et le plan ABC
  444. */
  445. double
  446. distance_point_plane (
  447. point3d * M,
  448. point3d * A,
  449. point3d * B,
  450. point3d * C)
  451. {
  452. double a,
  453. b,
  454. c,
  455. d;
  456. point3d p[3];
  457. point3d_init (&p[0], A->x, A->y, A->z);
  458. point3d_init (&p[1], B->x, B->y, B->z);
  459. point3d_init (&p[2], C->x, C->y, C->z);
  460. equation_plan (p, 3, &a, &b, &c, &d);
  461. return (fabs (a * M->x + b * M->y + c * M->z + d) /
  462. (sqrt (a * a + b * b + c * c)));
  463. }
  464. /**
  465. Calcule la distance entre un point M et un triangle défini par trois points A,b et C
  466. @param M point
  467. @param A premier point du triangle
  468. @param B second point du triangle
  469. @param C troisieme point du triangle
  470. @return distance entre le point M et le triangle ABC
  471. */
  472. double
  473. distance_point_triangle (
  474. point3d * M,
  475. point3d * A,
  476. point3d * B,
  477. point3d * C)
  478. {
  479. vector3d AB,
  480. AC,
  481. U,
  482. V;
  483. point2d Mb,
  484. Ab,
  485. Bb,
  486. Cb;
  487. point3d Mc,
  488. Ac,
  489. Bc,
  490. Cc;
  491. double d[3];
  492. vector3d_init (&AB, B->x - A->x, B->y - A->y, B->z - A->z);
  493. vector3d_init (&AC, C->x - A->x, C->y - A->y, C->z - A->z);
  494. vector3d_normalize (&AB);
  495. U = AB;
  496. find_second_base_vector (&AB, &AC, &V);
  497. base_modification_3d_to_2d (M, A, &U, &V, &Mb);
  498. base_modification_3d_to_2d (A, A, &U, &V, &Ab);
  499. base_modification_3d_to_2d (B, A, &U, &V, &Bb);
  500. base_modification_3d_to_2d (C, A, &U, &V, &Cb);
  501. point3d_init (&Mc, Mb.x, Mb.y, 0);
  502. point3d_init (&Ac, Ab.x, Ab.y, 0);
  503. point3d_init (&Bc, Bb.x, Bb.y, 0);
  504. point3d_init (&Cc, Cb.x, Cb.y, 0);
  505. if (point_in_triangle (&Mc, &Ac, &Bc, &Cc))
  506. return distance_point_plane (M, A, B, C);
  507. else
  508. {
  509. d[0] = point3d_length (M, A);
  510. d[1] = point3d_length (M, B);
  511. d[2] = point3d_length (M, C);
  512. list_double_sort (d, 3, ASC);
  513. return d[0];
  514. }
  515. }
  516. /**
  517. Echantillonne le triangle ABC
  518. @param A point A du triangle
  519. @param B point B
  520. @param C point C
  521. @param nb_sample nombre d'échantillon à extraire
  522. @param list tableau de réel représentant les coordonées des échantillons
  523. @param size taille du tableau
  524. @return aucun
  525. */
  526. void
  527. sample_triangle (
  528. const point3d * const A,
  529. const point3d * const B,
  530. const point3d * const C,
  531. int nb_sample,
  532. point3d ** list)
  533. {
  534. vector3d AB,
  535. AC;
  536. double alea1,
  537. alea2,
  538. alea3,
  539. somme,
  540. echx,
  541. echy,
  542. echz;
  543. *list = (point3d *) malloc (nb_sample * sizeof (point3d));
  544. a2ri_erreur_critique_si (*list == NULL,
  545. "erreur allocation memoire pour list\nsample_triangle");
  546. srand (time (NULL));
  547. vector3d_init (&AB, B->x - A->x, B->y - A->y, B->z - A->z);
  548. vector3d_init (&AC, C->x - A->x, C->y - A->y, C->z - A->z);
  549. for (int i = 0; i < nb_sample; i++)
  550. {
  551. alea1 = (rand () % 1000) / 1000.0;
  552. alea2 = (rand () % 1000) / 1000.0;
  553. alea3 = (rand () % 1000) / 1000.0;
  554. somme = alea1 + alea2 + alea3;
  555. alea1 /= somme;
  556. alea2 /= somme;
  557. alea3 /= somme;
  558. echx = A->x + alea1 * AB.dx + alea1 * AC.dx;
  559. echy = A->y + alea2 * AB.dy + alea2 * AC.dy;
  560. echz = A->z + alea3 * AB.dz + alea3 * AC.dz;
  561. (*list)[i].x = echx;
  562. (*list)[i].y = echy;
  563. (*list)[i].z = echz;
  564. }
  565. }
  566. /**
  567. Test de l'intersection entre une droite et un plan
  568. @param d1 premier point définissant la droite
  569. @param d2 second point définissant la droite
  570. @param p1 premier point du plan
  571. @param p2 second point du plan
  572. @param p3 troisieme point du plan
  573. @param t paramètre d'intersection
  574. @return 1 si intersection, 0 sinon
  575. */
  576. int
  577. intersection_droite_plan (
  578. point3d * d1,
  579. point3d * d2,
  580. point3d * p1,
  581. point3d * p2,
  582. point3d * p3,
  583. double *t)
  584. {
  585. vector3d N,
  586. rq;
  587. double D,
  588. num,
  589. denom;
  590. IFplanecoeff (p1, p2, p3, &N, &D);
  591. vector3d_init (&rq, d1->x, d1->y, d1->z);
  592. num = D - vector3d_scalarproduct (&rq, &N);
  593. vector3d_init (&rq, d2->x - d1->x, d2->y - d1->y, d2->z - d1->z);
  594. denom = vector3d_scalarproduct (&rq, &N);
  595. if (denom == 0.0)
  596. {
  597. if (num == 0.0)
  598. {
  599. *t = 0.0;
  600. return 1;
  601. }
  602. else
  603. return 0;
  604. }
  605. *t = num / denom;
  606. return 1;
  607. }
  608. /**
  609. Test de l'intersection entre une droite et un triangle
  610. @param d1 premier point définissant la droite
  611. @param d2 second point définissant la droite
  612. @param p1 premier point du triangle
  613. @param p2 second point du triangle
  614. @param p3 troisieme point du triangle
  615. @return 1 si intersection, 0 sinon
  616. */
  617. int
  618. intersection_droite_triangle (
  619. point3d * d1,
  620. point3d * d2,
  621. point3d * p1,
  622. point3d * p2,
  623. point3d * p3,
  624. double *t)
  625. {
  626. point3d inter;
  627. intersection_droite_plan (d1, d2, p1, p2, p3, t);
  628. point3d_init (&inter, d1->x + (*t) * (d2->x - d1->x),
  629. d1->y + (*t) * (d2->y - d1->y), d1->z + (*t) * (d2->z - d1->z));
  630. return point_in_triangle (&inter, p1, p2, p3);
  631. }
  632. /**
  633. Test de l'intersection entre un segment et un triangle
  634. @param s1 premier point définissant le segment
  635. @param s2 second point définissant le segment
  636. @param p1 premier point du triangle
  637. @param p2 second point du triangle
  638. @param p3 troisieme point du triangle
  639. @return 1 si intersection, 0 sinon
  640. */
  641. int
  642. intersection_segment_triangle (
  643. point3d * s1,
  644. point3d * s2,
  645. point3d * p1,
  646. point3d * p2,
  647. point3d * p3,
  648. double *t)
  649. {
  650. point3d inter;
  651. intersection_droite_plan (s1, s2, p1, p2, p3, t);
  652. if(*t>=0 && *t<=1.0){
  653. point3d_init (&inter, s1->x + (*t) * (s2->x - s1->x),
  654. s1->y + (*t) * (s2->y - s1->y), s1->z + (*t) * (s2->z - s1->z));
  655. return point_in_triangle (&inter, p1, p2, p3);
  656. }
  657. return 0;
  658. }
  659. /**
  660. Test de l'intersection entre deux triangles
  661. @param t1 premier point définissant le premier triangle
  662. @param t2 second point définissant le premier triangle
  663. @param t3 troisieme point définissant le premier triangle
  664. @param p1 premier point du second triangle
  665. @param p2 second point du second triangle
  666. @param p3 troisieme point du second triangle
  667. @return 1 si intersection, 0 sinon
  668. */
  669. int
  670. intersection_triangle_triangle (
  671. point3d * t1,
  672. point3d * t2,
  673. point3d * t3,
  674. point3d * p1,
  675. point3d * p2,
  676. point3d * p3)
  677. {
  678. double t;
  679. if (intersection_droite_triangle (t1, t2, p1, p2, p3, &t))
  680. {
  681. if (t >= 0 && t <= 1)
  682. return 1;
  683. }
  684. if (intersection_droite_triangle (t1, t3, p1, p2, p3, &t))
  685. {
  686. if (t >= 0 && t <= 1)
  687. return 1;
  688. }
  689. if (intersection_droite_triangle (t2, t3, p1, p2, p3, &t))
  690. {
  691. if (t >= 0 && t <= 1)
  692. return 1;
  693. }
  694. if (intersection_droite_triangle (p1, p2, t1, t2, t3, &t))
  695. {
  696. if (t >= 0 && t <= 1)
  697. return 1;
  698. }
  699. if (intersection_droite_triangle (p1, p3, t1, t2, t3, &t))
  700. {
  701. if (t >= 0 && t <= 1)
  702. return 1;
  703. }
  704. if (intersection_droite_triangle (p2, p3, t1, t2, t3, &t))
  705. {
  706. if (t >= 0 && t <= 1)
  707. return 1;
  708. }
  709. return 0;
  710. }
  711. /**
  712. Teste si les trois points A, B et C sont alignés
  713. @param A premier point
  714. @param B second point
  715. @param C troisieme point
  716. @return 1 si les trois points sont alignés, 0 sinon
  717. */
  718. int
  719. trois_points_alignes (
  720. point3d * A,
  721. point3d * B,
  722. point3d * C)
  723. {
  724. double t;
  725. if (point3d_equal (A, B))
  726. return 1;
  727. if (point3d_equal (A, C))
  728. return 1;
  729. if (point3d_equal (B, C))
  730. return 1;
  731. if (B->x - A->x != 0)
  732. t = (C->x - A->x) / (B->x - A->x);
  733. else
  734. {
  735. if (B->y - A->y != 0)
  736. t = (C->y - A->y) / (B->y - A->y);
  737. else
  738. t = (C->z - A->z) / (B->z - A->z);
  739. }
  740. if (!egalite (A->x + t * (B->x - A->x), C->x))
  741. return 0;
  742. if (!egalite (A->y + t * (B->y - A->y), C->y))
  743. return 0;
  744. if (!egalite (A->z + t * (B->z - A->z), C->z))
  745. return 0;
  746. return 1;
  747. }