ToolsMath.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. #include "stdafx.h"
  2. #include "ToolsMAth.h"
  3. #include <cmath>
  4. #include <limits>
  5. //------------------------------------------------------//
  6. // Fonctions Mathématiques diverses (by CJ) //
  7. //------------------------------------------------------//
  8. int round(double x)
  9. {
  10. return (int)( (x - floor(x)) >=0.5 ? ceil(x) : floor(x) );
  11. }
  12. // Calcul la distance entre 2 points
  13. double distance(dpoint pt1, dpoint pt2)
  14. {
  15. double dist;
  16. dist = std::sqrt((pt1.x - pt2.x) * (pt1.x - pt2.x) + (pt1.y - pt2.y) * (pt1.y - pt2.y));
  17. if (dist < 0.000001)
  18. {
  19. dist = 0;
  20. }
  21. return dist;
  22. }
  23. // Renvoie les coefficients p1 et d1 de la droite y = p1.x + b1, à partir de 2 points
  24. void GetCoeffDroite(dpoint pt1, dpoint pt2, double *p1, double *d1, double *b1)
  25. {
  26. // Leger bug pour des écarts très petits
  27. if (fabs(pt1.x - pt2.x) < 0.001)
  28. {
  29. pt1.x = pt2.x;
  30. }
  31. if (fabs(pt1.y - pt2.y) < 0.001)
  32. {
  33. pt1.y = pt2.y;
  34. }
  35. // Calcul des coefficients de la droite
  36. *p1 = INT_MAX;
  37. *d1 = pt2.x - pt1.x;
  38. if (*d1 != 0)
  39. {
  40. *p1 = (pt2.y - pt1.y) / (*d1);
  41. *b1 = pt1.y - ((*p1) * pt1.x);
  42. }
  43. }
  44. // Renvoie le point (sol1 ou sol2) le plus proche de p1
  45. dpoint leplusproche(dpoint vPoint, dpoint sol1, dpoint sol2)
  46. {
  47. double dist1, dist2;
  48. dpoint res;
  49. dist1 = distance(vPoint, sol1);
  50. dist2 = distance(vPoint, sol2);
  51. if (dist1 < dist2)
  52. {
  53. res.x = sol1.x;
  54. res.y = sol1.y;
  55. }
  56. else
  57. {
  58. res.x = sol2.x;
  59. res.y = sol2.y;
  60. }
  61. return res;
  62. }
  63. // Calcul des 2 points d'intersection entre un cercle et une droite définie par 2 points
  64. bool InterCercleDroite(dpoint p0, double r, dpoint d1, dpoint d2, dpoint *sr1, dpoint *sr2)
  65. {
  66. double a, b, d;
  67. double ka, kb, kc, delta;
  68. dpoint s1, s2;
  69. bool trouve = false;
  70. s1.x = -1;
  71. s1.y = -1;
  72. s2.x = -1;
  73. s2.y = -1;
  74. // Coefficient de la droite définie par 2 pts successifs
  75. // Droite y = a.x + b
  76. GetCoeffDroite(d1, d2, &a, &d, &b);
  77. if ((d != 0) && (a != 0))
  78. { // Cas normal
  79. ka = 1 + (a * a);
  80. kb = (2 * a * b) - (2 * p0.x) - (2 * a * p0.y);
  81. kc = (b * b) - (2 * b * p0.y) - ((r * r) - (p0.x * p0.x) - (p0.y * p0.y));
  82. delta = (kb * kb) - (4 * ka * kc);
  83. if (delta == 0)
  84. {
  85. s1.x = -kb / (2 * ka);
  86. s2.x = s1.x;
  87. }
  88. else if (delta > 0)
  89. {
  90. s1.x = (-kb - sqrt(delta)) / (2 * ka);
  91. s2.x = (-kb + sqrt(delta)) / (2 * ka);
  92. }
  93. if (delta >= 0)
  94. {
  95. s1.y = a * s1.x + b;
  96. s2.y = a * s2.x + b;
  97. trouve = true;
  98. }
  99. }
  100. else if (d == 0)
  101. { // La droite est verticale
  102. ka = 1;
  103. kb = -2 * p0.y;
  104. kc = (d1.x * d1.x) - (2 * d1.x * p0.x) - ((r * r) - (p0.x * p0.x) - (p0.y * p0.y));
  105. delta = (kb * kb) - (4 * ka * kc);
  106. if (delta == 0)
  107. {
  108. s1.y = -kb / (2 * ka);
  109. s2.y = s1.y;
  110. }
  111. else if (delta > 0)
  112. {
  113. s1.y = (-kb - sqrt(delta)) / (2 * ka);
  114. s2.y = (-kb + sqrt(delta)) / (2 * ka);
  115. }
  116. if (delta >= 0)
  117. {
  118. s1.x = d1.x;
  119. s2.x = d1.x;
  120. trouve = true;
  121. }
  122. }
  123. else if (a == 0)
  124. { // La droite est horizontale
  125. ka = 1;
  126. kb = -2 * p0.x;
  127. kc = (d1.y * d1.y) - (2 * d1.y * p0.y) - ((r * r) - (p0.x * p0.x) - (p0.y * p0.y));
  128. delta = (kb * kb) - (4 * ka * kc);
  129. if (delta == 0)
  130. {
  131. s1.x = -kb / (2 * ka);
  132. s2.x = s1.x;
  133. }
  134. else if (delta > 0)
  135. {
  136. s1.x = (-kb - sqrt(delta)) / (2 * ka);
  137. s2.x = (-kb + sqrt(delta)) / (2 * ka);
  138. }
  139. if (delta >= 0)
  140. {
  141. s1.y = d1.y;
  142. s2.y = d1.y;
  143. trouve = true;
  144. }
  145. }
  146. sr1->x = s1.x;
  147. sr1->y = s1.y;
  148. sr2->x = s2.x;
  149. sr2->y = s2.y;
  150. return trouve;
  151. }
  152. // Parabole y = a*x^2 + b*x + c (by FP)
  153. //
  154. // N : nombre de points (i.e. taille des vecteurs x[] et y[])
  155. // x : vecteurs des abscisses
  156. // y : vecteurs des ordonees
  157. // a, b, c : les 3 coefficients recherches
  158. void moindres_carres_parabole(int N, dpoint *points, double *a, double *b, double *c)
  159. {
  160. int i;
  161. double d, d1, d2, d3;
  162. double sx = 0.0;
  163. double sx2 = 0.0;
  164. double sx3 = 0.0;
  165. double sx4 = 0.0;
  166. double sy = 0.0;
  167. double syx = 0.0;
  168. double syx2 = 0.0;
  169. double x2;
  170. for ( i = 0; i < N; i++ )
  171. {
  172. sx += points[i].x;
  173. sx2 += ( x2 = points[i].x * points[i].x );
  174. sx3 += x2 * points[i].x;
  175. sx4 += x2 * x2;
  176. sy += points[i].y;
  177. syx += points[i].y * points[i].x;
  178. syx2 += points[i].y * x2;
  179. }
  180. d = sx4 * ( (double) N * sx2 - sx * sx ) + sx3 * ( sx * sx2 - (double) N * sx3 ) + sx2 * ( sx * sx3 - sx2 * sx2 );
  181. d1 = sx4 * ( sx2 * sy - sx * syx ) + sx3 * ( sx * syx2 - sx3 * sy) + sx2 * ( sx3 * syx - sx2 * syx2 );
  182. d2 = sx4 * ( (double) N * syx - sy * sx ) + sx3 * ( sy * sx2 - (double) N * syx2 ) + sx2 * ( syx2 * sx - syx * sx2 );
  183. d3 = syx2 * ( (double) N * sx2 - sx * sx ) + syx * ( sx * sx2 - (double) N * sx3 ) + sy * ( sx * sx3 - sx2 * sx2 );
  184. if (d != 0)
  185. {
  186. *c = d1 / d;
  187. *b = d2 / d;
  188. *a = d3 / d;
  189. }
  190. else
  191. {
  192. *a = *b = *c = 0;
  193. }
  194. }
  195. // Regression linéaire
  196. // Trouve les coefficients de la droite y = bx + a, à partir des points, par regression linéaire
  197. void RegressionLineaire(int n, dpoint *points, double *b, double *a)
  198. {
  199. // calculate the averages of arrays x and y
  200. double xa = 0, ya = 0;
  201. for (int i = 0; i < n; i++)
  202. {
  203. xa += points[i].x;
  204. ya += points[i].y;
  205. }
  206. if (n != 0)
  207. {
  208. xa /= n;
  209. ya /= n;
  210. }
  211. else
  212. {
  213. xa = 0;
  214. ya = 0;
  215. }
  216. // calculate auxiliary sums
  217. double xx = 0, yy = 0, xy = 0;
  218. for (int i = 0; i < n; i++)
  219. {
  220. double tmpx = points[i].x - xa, tmpy = points[i].y - ya;
  221. xx += tmpx * tmpx;
  222. yy += tmpy * tmpy;
  223. xy += tmpx * tmpy;
  224. }
  225. // calculate regression line parameters
  226. // make sure slope is not infinite
  227. // assert(fabs(xx) != 0);
  228. if (xx != 0)
  229. {
  230. *b = xy / xx;
  231. }
  232. else
  233. {
  234. *b = 0;
  235. }
  236. *a = ya - *b * xa;
  237. // Coefficient de regression
  238. // double coeff;
  239. // coeff = (fabs(yy) == 0) ? 1 : xy / sqrt(xx * yy);
  240. }
  241. // Calcul la distance orthogonale entre le point vpt
  242. // et la droite définie par les 2 points pt1 et pt2
  243. double distanceOrthPtDroite(dpoint vpt, dpoint pt1, dpoint pt2, dpoint *pres)
  244. {
  245. double p1, d1, b1, b2, dist;
  246. GetCoeffDroite(pt1, pt2, &p1, &d1, &b1);
  247. if ((p1 != 0) && (d1 != 0))
  248. {
  249. // Perpendiculaire qui passe par vpt
  250. b2 = vpt.y + ((1/p1) * vpt.x);
  251. // Point de rencontre (qui passe par pb)
  252. pres->x = (double) (b2 - b1) / (double) (p1 + (1/p1));
  253. pres->y = (double) p1 * (pres->x) + b1;
  254. }
  255. else if (p1 == 0)
  256. { // pt1-pt2 horizontale
  257. pres->x = vpt.x;
  258. pres->y = pt1.y;
  259. }
  260. else if (d1 == 0)
  261. { // verticale
  262. pres->x = pt1.x;
  263. pres->y = vpt.y;
  264. }
  265. dist = distance(*pres, vpt);
  266. return dist;
  267. }
  268. // Point in Polygon d'après FAQ comp.graphics
  269. bool PtInPolygon(double vx, double vy, dpoint *tpoint, int nbpoint)
  270. {
  271. int i, j;
  272. bool c = false;
  273. for (i = 0, j = nbpoint-1; i < nbpoint; j = i++)
  274. {
  275. if ((((tpoint[i].y <= vy) && (vy < tpoint[j].y))
  276. || ((tpoint[j].y <= vy) && (vy < tpoint[i].y))) &&
  277. (vx < (tpoint[j].x - tpoint[i].x) * (vy - tpoint[i].y) / (tpoint[j].y - tpoint[i].y) + tpoint[i].x))
  278. {
  279. c = !c;
  280. }
  281. }
  282. return c;
  283. }
  284. // Est ce que le point x, y est dans l'ellipse a, b
  285. bool PtInEllipse(double x, double y, double a, double b)
  286. {
  287. double result = 10.0;
  288. if ((a != 0.0) && (b != 0.0))
  289. {
  290. result = ((x / a) * (x / a)) + ((y / b) * (y / b));
  291. }
  292. if (result <= 1)
  293. {
  294. return true;
  295. }
  296. return false;
  297. }
  298. bool PtInEllipse2(int left, int right, int top, int bottom, int ptx, int pty)
  299. {
  300. double rqy;
  301. int ptcx;
  302. int ptcy;
  303. int qx;
  304. int qy;
  305. int rqx;
  306. int sizex;
  307. int sizey;
  308. if ((ptx < left) || (ptx > right) || (pty < top) || (pty > bottom))
  309. {
  310. return false;
  311. }
  312. sizex = right - left;
  313. sizey = bottom - top;
  314. if (sizex == 0 || sizey == 0)
  315. {
  316. return false;
  317. }
  318. ptcx = (left + right) / 2;
  319. ptcy = (top + bottom) / 2;
  320. qx = (ptcx - ptx) * (ptcx - ptx);
  321. qy = (ptcy - pty) * (ptcy - pty);
  322. rqx = (sizex) * (sizex) / 4;
  323. rqy = ((double) ((sizey) / (sizex)) * (double) ((sizey) / (sizex)) ) * ( rqx - qx );
  324. if (qy > rqy)
  325. {
  326. return false;
  327. }
  328. return true;
  329. }
  330. bool PtInEllipse3(int left, int right, int top, int bottom, int ptx, int pty)
  331. {
  332. double ax, bx;
  333. int ptcx;
  334. int ptcy;
  335. int sizex;
  336. int sizey;
  337. if ((ptx < left) || (ptx > right) || (pty < top) || (pty > bottom))
  338. {
  339. return false;
  340. }
  341. sizex = right - left;
  342. sizey = bottom - top;
  343. if (sizex == 0 || sizey == 0)
  344. {
  345. return false;
  346. }
  347. ptcx = (left + right) / 2;
  348. ptcy = (top + bottom) / 2;
  349. ax = ((double) (ptx - ptcx) / (double) sizex) * ((double) (ptx - ptcx) / (double) sizex);
  350. bx = ((double) (pty - ptcy) / (double) sizey) * ((double) (pty - ptcy) / (double) sizey);
  351. if ((ax + bx) < 0.25)
  352. {
  353. return true;
  354. }
  355. return false;
  356. }
  357. void Rotation(int X, int Y, float S, float C, int R, int P, int *Xp, int *Yp)
  358. {
  359. int Xx,Yy;
  360. Xx = X -R ;
  361. Yy = Y - P;
  362. *Xp = (int) (Xx * C - Yy * S + 0.5) + R;
  363. *Yp = (int) (Xx * S + Yy * C + 0.5) + P;
  364. }